annotate core/modules/node/tests/src/Functional/NodeTranslationUITest.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents af1871eacc83
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\Tests\node\Functional;
Chris@0 4
Chris@0 5 use Drupal\Core\Entity\EntityInterface;
Chris@0 6 use Drupal\Tests\content_translation\Functional\ContentTranslationUITestBase;
Chris@0 7 use Drupal\Core\Language\LanguageInterface;
Chris@0 8 use Drupal\Core\Url;
Chris@0 9 use Drupal\node\Entity\Node;
Chris@0 10 use Drupal\language\Entity\ConfigurableLanguage;
Chris@0 11
Chris@0 12 /**
Chris@0 13 * Tests the Node Translation UI.
Chris@0 14 *
Chris@0 15 * @group node
Chris@0 16 */
Chris@0 17 class NodeTranslationUITest extends ContentTranslationUITestBase {
Chris@0 18
Chris@0 19 /**
Chris@0 20 * {inheritdoc}
Chris@0 21 */
Chris@0 22 protected $defaultCacheContexts = [
Chris@0 23 'languages:language_interface',
Chris@0 24 'theme',
Chris@0 25 'route',
Chris@0 26 'timezone',
Chris@0 27 'url.path.parent',
Chris@0 28 'url.query_args:_wrapper_format',
Chris@18 29 'url.site',
Chris@14 30 'user.roles',
Chris@17 31 'url.path.is_front',
Chris@14 32 // These two cache contexts are added by BigPipe.
Chris@14 33 'cookies:big_pipe_nojs',
Chris@14 34 'session.exists',
Chris@0 35 ];
Chris@0 36
Chris@0 37 /**
Chris@0 38 * Modules to enable.
Chris@0 39 *
Chris@0 40 * @var array
Chris@0 41 */
Chris@0 42 public static $modules = ['block', 'language', 'content_translation', 'node', 'datetime', 'field_ui', 'help'];
Chris@0 43
Chris@0 44 /**
Chris@0 45 * The profile to install as a basis for testing.
Chris@0 46 *
Chris@0 47 * @var string
Chris@0 48 */
Chris@0 49 protected $profile = 'standard';
Chris@0 50
Chris@0 51 protected function setUp() {
Chris@0 52 $this->entityTypeId = 'node';
Chris@0 53 $this->bundle = 'article';
Chris@0 54 parent::setUp();
Chris@0 55
Chris@0 56 // Ensure the help message is shown even with prefixed paths.
Chris@0 57 $this->drupalPlaceBlock('help_block', ['region' => 'content']);
Chris@0 58
Chris@0 59 // Display the language selector.
Chris@0 60 $this->drupalLogin($this->administrator);
Chris@0 61 $edit = ['language_configuration[language_alterable]' => TRUE];
Chris@0 62 $this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
Chris@0 63 $this->drupalLogin($this->translator);
Chris@0 64 }
Chris@0 65
Chris@0 66 /**
Chris@0 67 * Tests the basic translation UI.
Chris@0 68 */
Chris@0 69 public function testTranslationUI() {
Chris@0 70 parent::testTranslationUI();
Chris@0 71 $this->doUninstallTest();
Chris@0 72 }
Chris@0 73
Chris@0 74 /**
Chris@0 75 * Tests changing the published status on a node without fields.
Chris@0 76 */
Chris@0 77 public function testPublishedStatusNoFields() {
Chris@0 78 // Test changing the published status of an article without fields.
Chris@0 79 $this->drupalLogin($this->administrator);
Chris@0 80 // Delete all fields.
Chris@0 81 $this->drupalGet('admin/structure/types/manage/article/fields');
Chris@0 82 $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.' . $this->fieldName . '/delete', [], t('Delete'));
Chris@0 83 $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_tags/delete', [], t('Delete'));
Chris@0 84 $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_image/delete', [], t('Delete'));
Chris@0 85
Chris@0 86 // Add a node.
Chris@0 87 $default_langcode = $this->langcodes[0];
Chris@0 88 $values[$default_langcode] = ['title' => [['value' => $this->randomMachineName()]]];
Chris@0 89 $this->entityId = $this->createEntity($values[$default_langcode], $default_langcode);
Chris@0 90 $storage = $this->container->get('entity_type.manager')
Chris@0 91 ->getStorage($this->entityTypeId);
Chris@0 92 $storage->resetCache([$this->entityId]);
Chris@0 93 $entity = $storage->load($this->entityId);
Chris@0 94
Chris@0 95 // Add a content translation.
Chris@0 96 $langcode = 'fr';
Chris@0 97 $language = ConfigurableLanguage::load($langcode);
Chris@0 98 $values[$langcode] = ['title' => [['value' => $this->randomMachineName()]]];
Chris@0 99
Chris@0 100 $entity_type_id = $entity->getEntityTypeId();
Chris@0 101 $add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [
Chris@0 102 $entity->getEntityTypeId() => $entity->id(),
Chris@0 103 'source' => $default_langcode,
Chris@17 104 'target' => $langcode,
Chris@0 105 ], ['language' => $language]);
Chris@0 106 $edit = $this->getEditValues($values, $langcode);
Chris@0 107 $edit['status[value]'] = FALSE;
Chris@0 108 $this->drupalPostForm($add_url, $edit, t('Save (this translation)'));
Chris@0 109
Chris@0 110 $storage->resetCache([$this->entityId]);
Chris@0 111 $entity = $storage->load($this->entityId);
Chris@0 112 $translation = $entity->getTranslation($langcode);
Chris@0 113 // Make sure we unpublished the node correctly.
Chris@0 114 $this->assertFalse($this->manager->getTranslationMetadata($translation)->isPublished(), 'The translation has been correctly unpublished.');
Chris@0 115 }
Chris@0 116
Chris@0 117 /**
Chris@0 118 * {@inheritdoc}
Chris@0 119 */
Chris@0 120 protected function getTranslatorPermissions() {
Chris@0 121 return array_merge(parent::getTranslatorPermissions(), ['administer nodes', "edit any $this->bundle content"]);
Chris@0 122 }
Chris@0 123
Chris@0 124 /**
Chris@0 125 * {@inheritdoc}
Chris@0 126 */
Chris@0 127 protected function getEditorPermissions() {
Chris@0 128 return ['administer nodes', 'create article content'];
Chris@0 129 }
Chris@0 130
Chris@0 131 /**
Chris@0 132 * {@inheritdoc}
Chris@0 133 */
Chris@0 134 protected function getAdministratorPermissions() {
Chris@0 135 return array_merge(parent::getAdministratorPermissions(), ['access administration pages', 'administer content types', 'administer node fields', 'access content overview', 'bypass node access', 'administer languages', 'administer themes', 'view the administration theme']);
Chris@0 136 }
Chris@0 137
Chris@0 138 /**
Chris@0 139 * {@inheritdoc}
Chris@0 140 */
Chris@0 141 protected function getNewEntityValues($langcode) {
Chris@0 142 return ['title' => [['value' => $this->randomMachineName()]]] + parent::getNewEntityValues($langcode);
Chris@0 143 }
Chris@0 144
Chris@0 145 /**
Chris@0 146 * {@inheritdoc}
Chris@0 147 */
Chris@0 148 protected function doTestPublishedStatus() {
Chris@0 149 $storage = $this->container->get('entity_type.manager')
Chris@0 150 ->getStorage($this->entityTypeId);
Chris@0 151 $storage->resetCache([$this->entityId]);
Chris@0 152 $entity = $storage->load($this->entityId);
Chris@0 153 $languages = $this->container->get('language_manager')->getLanguages();
Chris@0 154
Chris@0 155 $statuses = [
Chris@0 156 TRUE,
Chris@0 157 FALSE,
Chris@0 158 ];
Chris@0 159
Chris@0 160 foreach ($statuses as $index => $value) {
Chris@0 161 // (Un)publish the node translations and check that the translation
Chris@0 162 // statuses are (un)published accordingly.
Chris@0 163 foreach ($this->langcodes as $langcode) {
Chris@0 164 $options = ['language' => $languages[$langcode]];
Chris@18 165 $url = $entity->toUrl('edit-form', $options);
Chris@0 166 $this->drupalPostForm($url, ['status[value]' => $value], t('Save') . $this->getFormSubmitSuffix($entity, $langcode), $options);
Chris@0 167 }
Chris@0 168 $storage->resetCache([$this->entityId]);
Chris@0 169 $entity = $storage->load($this->entityId);
Chris@0 170 foreach ($this->langcodes as $langcode) {
Chris@0 171 // The node is created as unpublished thus we switch to the published
Chris@0 172 // status first.
Chris@0 173 $status = !$index;
Chris@0 174 $translation = $entity->getTranslation($langcode);
Chris@0 175 $this->assertEqual($status, $this->manager->getTranslationMetadata($translation)->isPublished(), 'The translation has been correctly unpublished.');
Chris@0 176 }
Chris@0 177 }
Chris@0 178 }
Chris@0 179
Chris@0 180 /**
Chris@0 181 * {@inheritdoc}
Chris@0 182 */
Chris@0 183 protected function doTestAuthoringInfo() {
Chris@0 184 $storage = $this->container->get('entity_type.manager')
Chris@0 185 ->getStorage($this->entityTypeId);
Chris@0 186 $storage->resetCache([$this->entityId]);
Chris@0 187 $entity = $storage->load($this->entityId);
Chris@0 188 $languages = $this->container->get('language_manager')->getLanguages();
Chris@0 189 $values = [];
Chris@0 190
Chris@0 191 // Post different base field information for each translation.
Chris@0 192 foreach ($this->langcodes as $langcode) {
Chris@0 193 $user = $this->drupalCreateUser();
Chris@0 194 $values[$langcode] = [
Chris@0 195 'uid' => $user->id(),
Chris@0 196 'created' => REQUEST_TIME - mt_rand(0, 1000),
Chris@0 197 'sticky' => (bool) mt_rand(0, 1),
Chris@0 198 'promote' => (bool) mt_rand(0, 1),
Chris@0 199 ];
Chris@18 200 /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
Chris@18 201 $date_formatter = $this->container->get('date.formatter');
Chris@0 202 $edit = [
Chris@18 203 'uid[0][target_id]' => $user->getAccountName(),
Chris@18 204 'created[0][value][date]' => $date_formatter->format($values[$langcode]['created'], 'custom', 'Y-m-d'),
Chris@18 205 'created[0][value][time]' => $date_formatter->format($values[$langcode]['created'], 'custom', 'H:i:s'),
Chris@0 206 'sticky[value]' => $values[$langcode]['sticky'],
Chris@0 207 'promote[value]' => $values[$langcode]['promote'],
Chris@0 208 ];
Chris@0 209 $options = ['language' => $languages[$langcode]];
Chris@18 210 $url = $entity->toUrl('edit-form', $options);
Chris@0 211 $this->drupalPostForm($url, $edit, $this->getFormSubmitAction($entity, $langcode), $options);
Chris@0 212 }
Chris@0 213
Chris@0 214 $storage->resetCache([$this->entityId]);
Chris@0 215 $entity = $storage->load($this->entityId);
Chris@0 216 foreach ($this->langcodes as $langcode) {
Chris@0 217 $translation = $entity->getTranslation($langcode);
Chris@0 218 $metadata = $this->manager->getTranslationMetadata($translation);
Chris@0 219 $this->assertEqual($metadata->getAuthor()->id(), $values[$langcode]['uid'], 'Translation author correctly stored.');
Chris@0 220 $this->assertEqual($metadata->getCreatedTime(), $values[$langcode]['created'], 'Translation date correctly stored.');
Chris@0 221 $this->assertEqual($translation->isSticky(), $values[$langcode]['sticky'], 'Sticky of Translation correctly stored.');
Chris@0 222 $this->assertEqual($translation->isPromoted(), $values[$langcode]['promote'], 'Promoted of Translation correctly stored.');
Chris@0 223 }
Chris@0 224 }
Chris@0 225
Chris@0 226 /**
Chris@0 227 * Tests that translation page inherits admin status of edit page.
Chris@0 228 */
Chris@0 229 public function testTranslationLinkTheme() {
Chris@0 230 $this->drupalLogin($this->administrator);
Chris@0 231 $article = $this->drupalCreateNode(['type' => 'article', 'langcode' => $this->langcodes[0]]);
Chris@0 232
Chris@0 233 // Set up Seven as the admin theme and use it for node editing.
Chris@0 234 $this->container->get('theme_handler')->install(['seven']);
Chris@0 235 $edit = [];
Chris@0 236 $edit['admin_theme'] = 'seven';
Chris@0 237 $edit['use_admin_theme'] = TRUE;
Chris@0 238 $this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
Chris@0 239 $this->drupalGet('node/' . $article->id() . '/translations');
Chris@0 240 $this->assertRaw('core/themes/seven/css/base/elements.css', 'Translation uses admin theme if edit is admin.');
Chris@0 241
Chris@0 242 // Turn off admin theme for editing, assert inheritance to translations.
Chris@0 243 $edit['use_admin_theme'] = FALSE;
Chris@0 244 $this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
Chris@0 245 $this->drupalGet('node/' . $article->id() . '/translations');
Chris@0 246 $this->assertNoRaw('core/themes/seven/css/base/elements.css', 'Translation uses frontend theme if edit is frontend.');
Chris@0 247
Chris@0 248 // Assert presence of translation page itself (vs. DisabledBundle below).
Chris@0 249 $this->assertResponse(200);
Chris@0 250 }
Chris@0 251
Chris@0 252 /**
Chris@0 253 * Tests that no metadata is stored for a disabled bundle.
Chris@0 254 */
Chris@0 255 public function testDisabledBundle() {
Chris@0 256 // Create a bundle that does not have translation enabled.
Chris@0 257 $disabledBundle = $this->randomMachineName();
Chris@0 258 $this->drupalCreateContentType(['type' => $disabledBundle, 'name' => $disabledBundle]);
Chris@0 259
Chris@0 260 // Create a node for each bundle.
Chris@0 261 $node = $this->drupalCreateNode([
Chris@0 262 'type' => $this->bundle,
Chris@0 263 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
Chris@0 264 ]);
Chris@0 265
Chris@0 266 // Make sure that nothing was inserted into the {content_translation} table.
Chris@0 267 $rows = db_query('SELECT nid, count(nid) AS count FROM {node_field_data} WHERE type <> :type GROUP BY nid HAVING count(nid) >= 2', [':type' => $this->bundle])->fetchAll();
Chris@0 268 $this->assertEqual(0, count($rows));
Chris@0 269
Chris@0 270 // Ensure the translation tab is not accessible.
Chris@0 271 $this->drupalGet('node/' . $node->id() . '/translations');
Chris@0 272 $this->assertResponse(403);
Chris@0 273 }
Chris@0 274
Chris@0 275 /**
Chris@0 276 * Tests that translations are rendered properly.
Chris@0 277 */
Chris@0 278 public function testTranslationRendering() {
Chris@0 279 $default_langcode = $this->langcodes[0];
Chris@0 280 $values[$default_langcode] = $this->getNewEntityValues($default_langcode);
Chris@0 281 $this->entityId = $this->createEntity($values[$default_langcode], $default_langcode);
Chris@0 282 $node = \Drupal::entityManager()->getStorage($this->entityTypeId)->load($this->entityId);
Chris@0 283 $node->setPromoted(TRUE);
Chris@0 284
Chris@0 285 // Create translations.
Chris@0 286 foreach (array_diff($this->langcodes, [$default_langcode]) as $langcode) {
Chris@0 287 $values[$langcode] = $this->getNewEntityValues($langcode);
Chris@0 288 $translation = $node->addTranslation($langcode, $values[$langcode]);
Chris@0 289 // Publish and promote the translation to frontpage.
Chris@0 290 $translation->setPromoted(TRUE);
Chris@17 291 $translation->setPublished();
Chris@0 292 }
Chris@0 293 $node->save();
Chris@0 294
Chris@0 295 // Test that the frontpage view displays the correct translations.
Chris@0 296 \Drupal::service('module_installer')->install(['views'], TRUE);
Chris@0 297 $this->rebuildContainer();
Chris@0 298 $this->doTestTranslations('node', $values);
Chris@0 299
Chris@0 300 // Enable the translation language renderer.
Chris@0 301 $view = \Drupal::entityManager()->getStorage('view')->load('frontpage');
Chris@0 302 $display = &$view->getDisplay('default');
Chris@0 303 $display['display_options']['rendering_language'] = '***LANGUAGE_entity_translation***';
Chris@0 304 $view->save();
Chris@0 305
Chris@0 306 // Need to check from the beginning, including the base_path, in the url
Chris@0 307 // since the pattern for the default language might be a substring of
Chris@0 308 // the strings for other languages.
Chris@0 309 $base_path = base_path();
Chris@0 310
Chris@0 311 // Check the frontpage for 'Read more' links to each translation.
Chris@0 312 // See also assertTaxonomyPage() in NodeAccessBaseTableTest.
Chris@0 313 $node_href = 'node/' . $node->id();
Chris@0 314 foreach ($this->langcodes as $langcode) {
Chris@0 315 $this->drupalGet('node', ['language' => \Drupal::languageManager()->getLanguage($langcode)]);
Chris@0 316 $num_match_found = 0;
Chris@0 317 if ($langcode == 'en') {
Chris@0 318 // Site default language does not have langcode prefix in the URL.
Chris@0 319 $expected_href = $base_path . $node_href;
Chris@0 320 }
Chris@0 321 else {
Chris@0 322 $expected_href = $base_path . $langcode . '/' . $node_href;
Chris@0 323 }
Chris@0 324 $pattern = '|^' . $expected_href . '$|';
Chris@0 325 foreach ($this->xpath("//a[text()='Read more']") as $link) {
Chris@0 326 if (preg_match($pattern, $link->getAttribute('href'), $matches) == TRUE) {
Chris@0 327 $num_match_found++;
Chris@0 328 }
Chris@0 329 }
Chris@0 330 $this->assertTrue($num_match_found == 1, 'There is 1 Read more link, ' . $expected_href . ', for the ' . $langcode . ' translation of a node on the frontpage. (Found ' . $num_match_found . '.)');
Chris@0 331 }
Chris@0 332
Chris@0 333 // Check the frontpage for 'Add new comment' links that include the
Chris@0 334 // language.
Chris@0 335 $comment_form_href = 'node/' . $node->id() . '#comment-form';
Chris@0 336 foreach ($this->langcodes as $langcode) {
Chris@0 337 $this->drupalGet('node', ['language' => \Drupal::languageManager()->getLanguage($langcode)]);
Chris@0 338 $num_match_found = 0;
Chris@0 339 if ($langcode == 'en') {
Chris@0 340 // Site default language does not have langcode prefix in the URL.
Chris@0 341 $expected_href = $base_path . $comment_form_href;
Chris@0 342 }
Chris@0 343 else {
Chris@0 344 $expected_href = $base_path . $langcode . '/' . $comment_form_href;
Chris@0 345 }
Chris@0 346 $pattern = '|^' . $expected_href . '$|';
Chris@0 347 foreach ($this->xpath("//a[text()='Add new comment']") as $link) {
Chris@0 348 if (preg_match($pattern, $link->getAttribute('href'), $matches) == TRUE) {
Chris@0 349 $num_match_found++;
Chris@0 350 }
Chris@0 351 }
Chris@0 352 $this->assertTrue($num_match_found == 1, 'There is 1 Add new comment link, ' . $expected_href . ', for the ' . $langcode . ' translation of a node on the frontpage. (Found ' . $num_match_found . '.)');
Chris@0 353 }
Chris@0 354
Chris@0 355 // Test that the node page displays the correct translations.
Chris@0 356 $this->doTestTranslations('node/' . $node->id(), $values);
Chris@0 357
Chris@0 358 // Test that the node page has the correct alternate hreflang links.
Chris@18 359 $this->doTestAlternateHreflangLinks($node->toUrl());
Chris@0 360 }
Chris@0 361
Chris@0 362 /**
Chris@0 363 * Tests that the given path displays the correct translation values.
Chris@0 364 *
Chris@0 365 * @param string $path
Chris@0 366 * The path to be tested.
Chris@0 367 * @param array $values
Chris@0 368 * The translation values to be found.
Chris@0 369 */
Chris@0 370 protected function doTestTranslations($path, array $values) {
Chris@0 371 $languages = $this->container->get('language_manager')->getLanguages();
Chris@0 372 foreach ($this->langcodes as $langcode) {
Chris@0 373 $this->drupalGet($path, ['language' => $languages[$langcode]]);
Chris@0 374 $this->assertText($values[$langcode]['title'][0]['value'], format_string('The %langcode node translation is correctly displayed.', ['%langcode' => $langcode]));
Chris@0 375 }
Chris@0 376 }
Chris@0 377
Chris@0 378 /**
Chris@0 379 * Tests that the given path provides the correct alternate hreflang links.
Chris@0 380 *
Chris@0 381 * @param \Drupal\Core\Url $url
Chris@0 382 * The path to be tested.
Chris@0 383 */
Chris@0 384 protected function doTestAlternateHreflangLinks(Url $url) {
Chris@0 385 $languages = $this->container->get('language_manager')->getLanguages();
Chris@0 386 $url->setAbsolute();
Chris@0 387 $urls = [];
Chris@0 388 foreach ($this->langcodes as $langcode) {
Chris@0 389 $language_url = clone $url;
Chris@0 390 $urls[$langcode] = $language_url->setOption('language', $languages[$langcode]);
Chris@0 391 }
Chris@0 392 foreach ($this->langcodes as $langcode) {
Chris@0 393 $this->drupalGet($urls[$langcode]);
Chris@0 394 foreach ($urls as $alternate_langcode => $language_url) {
Chris@0 395 // Retrieve desired link elements from the HTML head.
Chris@0 396 $links = $this->xpath('head/link[@rel = "alternate" and @href = :href and @hreflang = :hreflang]',
Chris@0 397 [':href' => $language_url->toString(), ':hreflang' => $alternate_langcode]);
Chris@0 398 $this->assert(isset($links[0]), format_string('The %langcode node translation has the correct alternate hreflang link for %alternate_langcode: %link.', ['%langcode' => $langcode, '%alternate_langcode' => $alternate_langcode, '%link' => $url->toString()]));
Chris@0 399 }
Chris@0 400 }
Chris@0 401 }
Chris@0 402
Chris@0 403 /**
Chris@0 404 * {@inheritdoc}
Chris@0 405 */
Chris@0 406 protected function getFormSubmitSuffix(EntityInterface $entity, $langcode) {
Chris@0 407 if (!$entity->isNew() && $entity->isTranslatable()) {
Chris@0 408 $translations = $entity->getTranslationLanguages();
Chris@0 409 if ((count($translations) > 1 || !isset($translations[$langcode])) && ($field = $entity->getFieldDefinition('status'))) {
Chris@0 410 return ' ' . ($field->isTranslatable() ? t('(this translation)') : t('(all translations)'));
Chris@0 411 }
Chris@0 412 }
Chris@0 413 return '';
Chris@0 414 }
Chris@0 415
Chris@0 416 /**
Chris@0 417 * Tests uninstalling content_translation.
Chris@0 418 */
Chris@0 419 protected function doUninstallTest() {
Chris@0 420 // Delete all the nodes so there is no data.
Chris@0 421 $nodes = Node::loadMultiple();
Chris@0 422 foreach ($nodes as $node) {
Chris@0 423 $node->delete();
Chris@0 424 }
Chris@0 425 $language_count = count(\Drupal::configFactory()->listAll('language.content_settings.'));
Chris@0 426 \Drupal::service('module_installer')->uninstall(['content_translation']);
Chris@0 427 $this->rebuildContainer();
Chris@0 428 $this->assertEqual($language_count, count(\Drupal::configFactory()->listAll('language.content_settings.')), 'Languages have been fixed rather than deleted during content_translation uninstall.');
Chris@0 429 }
Chris@0 430
Chris@0 431 /**
Chris@0 432 * {@inheritdoc}
Chris@0 433 */
Chris@0 434 protected function doTestTranslationEdit() {
Chris@0 435 $storage = $this->container->get('entity_type.manager')
Chris@0 436 ->getStorage($this->entityTypeId);
Chris@0 437 $storage->resetCache([$this->entityId]);
Chris@0 438 $entity = $storage->load($this->entityId);
Chris@0 439 $languages = $this->container->get('language_manager')->getLanguages();
Chris@0 440 $type_name = node_get_type_label($entity);
Chris@0 441
Chris@0 442 foreach ($this->langcodes as $langcode) {
Chris@0 443 // We only want to test the title for non-english translations.
Chris@0 444 if ($langcode != 'en') {
Chris@0 445 $options = ['language' => $languages[$langcode]];
Chris@18 446 $url = $entity->toUrl('edit-form', $options);
Chris@0 447 $this->drupalGet($url);
Chris@0 448
Chris@0 449 $title = t('<em>Edit @type</em> @title [%language translation]', [
Chris@0 450 '@type' => $type_name,
Chris@0 451 '@title' => $entity->getTranslation($langcode)->label(),
Chris@0 452 '%language' => $languages[$langcode]->getName(),
Chris@0 453 ]);
Chris@0 454 $this->assertRaw($title);
Chris@0 455 }
Chris@0 456 }
Chris@0 457 }
Chris@0 458
Chris@0 459 /**
Chris@0 460 * Tests that revision translations are rendered properly.
Chris@0 461 */
Chris@0 462 public function testRevisionTranslationRendering() {
Chris@0 463 $storage = \Drupal::entityTypeManager()->getStorage('node');
Chris@0 464
Chris@0 465 // Create a node.
Chris@0 466 $nid = $this->createEntity(['title' => 'First rev en title'], 'en');
Chris@0 467 $node = $storage->load($nid);
Chris@0 468 $original_revision_id = $node->getRevisionId();
Chris@0 469
Chris@0 470 // Add a French translation.
Chris@0 471 $translation = $node->addTranslation('fr');
Chris@0 472 $translation->title = 'First rev fr title';
Chris@0 473 $translation->setNewRevision(FALSE);
Chris@0 474 $translation->save();
Chris@0 475
Chris@0 476 // Create a new revision.
Chris@0 477 $node->title = 'Second rev en title';
Chris@0 478 $node->setNewRevision(TRUE);
Chris@0 479 $node->save();
Chris@0 480
Chris@0 481 // Get an English view of this revision.
Chris@0 482 $original_revision = $storage->loadRevision($original_revision_id);
Chris@0 483 $original_revision_url = $original_revision->toUrl('revision')->toString();
Chris@0 484
Chris@0 485 // Should be different from regular node URL.
Chris@0 486 $this->assertNotIdentical($original_revision_url, $original_revision->toUrl()->toString());
Chris@0 487 $this->drupalGet($original_revision_url);
Chris@0 488 $this->assertResponse(200);
Chris@0 489
Chris@0 490 // Contents should be in English, of correct revision.
Chris@0 491 $this->assertText('First rev en title');
Chris@0 492 $this->assertNoText('First rev fr title');
Chris@0 493
Chris@0 494 // Get a French view.
Chris@0 495 $url_fr = $original_revision->getTranslation('fr')->toUrl('revision')->toString();
Chris@0 496
Chris@0 497 // Should have different URL from English.
Chris@0 498 $this->assertNotIdentical($url_fr, $original_revision->toUrl()->toString());
Chris@0 499 $this->assertNotIdentical($url_fr, $original_revision_url);
Chris@0 500 $this->drupalGet($url_fr);
Chris@0 501 $this->assertResponse(200);
Chris@0 502
Chris@0 503 // Contents should be in French, of correct revision.
Chris@0 504 $this->assertText('First rev fr title');
Chris@0 505 $this->assertNoText('First rev en title');
Chris@0 506 }
Chris@0 507
Chris@17 508 /**
Chris@17 509 * Test that title is not escaped (but XSS-filtered) for details form element.
Chris@17 510 */
Chris@17 511 public function testDetailsTitleIsNotEscaped() {
Chris@17 512 $this->drupalLogin($this->administrator);
Chris@17 513 // Make the image field a multi-value field in order to display a
Chris@17 514 // details form element.
Chris@17 515 $edit = ['cardinality_number' => 2];
Chris@17 516 $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_image/storage', $edit, t('Save field settings'));
Chris@17 517
Chris@17 518 // Make the image field non-translatable.
Chris@17 519 $edit = ['settings[node][article][fields][field_image]' => FALSE];
Chris@17 520 $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration'));
Chris@17 521
Chris@17 522 // Create a node.
Chris@17 523 $nid = $this->createEntity(['title' => 'Node with multi-value image field en title'], 'en');
Chris@17 524
Chris@17 525 // Add a French translation and assert the title markup is not escaped.
Chris@17 526 $this->drupalGet("node/$nid/translations/add/en/fr");
Chris@17 527 $markup = 'Image <span class="translation-entity-all-languages">(all languages)</span>';
Chris@17 528 $this->assertSession()->assertNoEscaped($markup);
Chris@17 529 $this->assertSession()->responseContains($markup);
Chris@17 530 }
Chris@17 531
Chris@0 532 }