Move into nested docroot

This commit is contained in:
Rob Davies 2017-02-13 15:31:17 +00:00
parent 83a0d3a149
commit c8b70abde9
13405 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,69 @@
<?php
namespace Drupal\taxonomy\Tests;
/**
* Verifies operation of a taxonomy-based Entity Query.
*
* @group taxonomy
*/
class EfqTest extends TaxonomyTestBase {
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy']));
$this->vocabulary = $this->createVocabulary();
}
/**
* Tests that a basic taxonomy entity query works.
*/
function testTaxonomyEfq() {
$terms = array();
for ($i = 0; $i < 5; $i++) {
$term = $this->createTerm($this->vocabulary);
$terms[$term->id()] = $term;
}
$result = \Drupal::entityQuery('taxonomy_term')->execute();
sort($result);
$this->assertEqual(array_keys($terms), $result, 'Taxonomy terms were retrieved by entity query.');
$tid = reset($result);
$ids = (object) array(
'entity_type' => 'taxonomy_term',
'entity_id' => $tid,
'bundle' => $this->vocabulary->id(),
);
$term = _field_create_entity_from_ids($ids);
$this->assertEqual($term->id(), $tid, 'Taxonomy term can be created based on the IDs.');
// Create a second vocabulary and five more terms.
$vocabulary2 = $this->createVocabulary();
$terms2 = array();
for ($i = 0; $i < 5; $i++) {
$term = $this->createTerm($vocabulary2);
$terms2[$term->id()] = $term;
}
$result = \Drupal::entityQuery('taxonomy_term')
->condition('vid', $vocabulary2->id())
->execute();
sort($result);
$this->assertEqual(array_keys($terms2), $result, format_string('Taxonomy terms from the %name vocabulary were retrieved by entity query.', array('%name' => $vocabulary2->label())));
$tid = reset($result);
$ids = (object) array(
'entity_type' => 'taxonomy_term',
'entity_id' => $tid,
'bundle' => $vocabulary2->id(),
);
$term = _field_create_entity_from_ids($ids);
$this->assertEqual($term->id(), $tid, 'Taxonomy term can be created based on the IDs.');
}
}

View file

@ -0,0 +1,69 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use \Drupal\taxonomy\Entity\Vocabulary;
/**
* Posts an article with a taxonomy term and a date prior to 1970.
*
* @group taxonomy
*/
class LegacyTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node', 'datetime');
protected function setUp() {
parent::setUp();
// Create a tags vocabulary for the 'article' content type.
$vocabulary = Vocabulary::create([
'name' => 'Tags',
'vid' => 'tags',
]);
$vocabulary->save();
$field_name = 'field_' . $vocabulary->id();
$handler_settings = array(
'target_bundles' => array(
$vocabulary->id() => $vocabulary->id(),
),
'auto_create' => TRUE,
);
$this->createEntityReferenceField('node', 'article', $field_name, 'Tags', 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
entity_get_form_display('node', 'article', 'default')
->setComponent($field_name, array(
'type' => 'entity_reference_autocomplete_tags',
))
->save();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'administer nodes', 'bypass node access']));
}
/**
* Test taxonomy functionality with nodes prior to 1970.
*/
function testTaxonomyLegacyNode() {
// Posts an article with a taxonomy term and a date prior to 1970.
$date = new DrupalDateTime('1969-01-01 00:00:00');
$edit = array();
$edit['title[0][value]'] = $this->randomMachineName();
$edit['created[0][value][date]'] = $date->format('Y-m-d');
$edit['created[0][value][time]'] = $date->format('H:i:s');
$edit['body[0][value]'] = $this->randomMachineName();
$edit['field_tags[target_id]'] = $this->randomMachineName();
$this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
// Checks that the node has been saved.
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$this->assertEqual($node->getCreatedTime(), $date->getTimestamp(), 'Legacy node was saved with the right date.');
}
}

View file

@ -0,0 +1,62 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\taxonomy\Entity\Term;
/**
* Tests the loading of multiple taxonomy terms at once.
*
* @group taxonomy
*/
class LoadMultipleTest extends TaxonomyTestBase {
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy']));
}
/**
* Create a vocabulary and some taxonomy terms, ensuring they're loaded
* correctly using entity_load_multiple().
*/
function testTaxonomyTermMultipleLoad() {
// Create a vocabulary.
$vocabulary = $this->createVocabulary();
// Create five terms in the vocabulary.
$i = 0;
while ($i < 5) {
$i++;
$this->createTerm($vocabulary);
}
// Load the terms from the vocabulary.
$terms = entity_load_multiple_by_properties('taxonomy_term', array('vid' => $vocabulary->id()));
$count = count($terms);
$this->assertEqual($count, 5, format_string('Correct number of terms were loaded. @count terms.', array('@count' => $count)));
// Load the same terms again by tid.
$terms2 = Term::loadMultiple(array_keys($terms));
$this->assertEqual($count, count($terms2), 'Five terms were loaded by tid.');
$this->assertEqual($terms, $terms2, 'Both arrays contain the same terms.');
// Remove one term from the array, then delete it.
$deleted = array_shift($terms2);
$deleted->delete();
$deleted_term = Term::load($deleted->id());
$this->assertFalse($deleted_term);
// Load terms from the vocabulary by vid.
$terms3 = entity_load_multiple_by_properties('taxonomy_term', array('vid' => $vocabulary->id()));
$this->assertEqual(count($terms3), 4, 'Correct number of terms were loaded.');
$this->assertFalse(isset($terms3[$deleted->id()]));
// Create a single term and load it by name.
$term = $this->createTerm($vocabulary);
$loaded_terms = entity_load_multiple_by_properties('taxonomy_term', array('name' => $term->getName()));
$this->assertEqual(count($loaded_terms), 1, 'One term was loaded.');
$loaded_term = reset($loaded_terms);
$this->assertEqual($term->id(), $loaded_term->id(), 'Term loaded by name successfully.');
}
}

View file

@ -0,0 +1,130 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\views\Views;
/**
* Ensure that data added as terms appears in RSS feeds if "RSS Category" format
* is selected.
*
* @group taxonomy
*/
class RssTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node', 'field_ui', 'views');
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* Name of the taxonomy term reference field.
*
* @var string
*/
protected $fieldName;
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'bypass node access', 'administer content types', 'administer node display']));
$this->vocabulary = $this->createVocabulary();
$this->fieldName = 'taxonomy_' . $this->vocabulary->id();
$handler_settings = array(
'target_bundles' => array(
$this->vocabulary->id() => $this->vocabulary->id(),
),
'auto_create' => TRUE,
);
$this->createEntityReferenceField('node', 'article', $this->fieldName, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
entity_get_form_display('node', 'article', 'default')
->setComponent($this->fieldName, array(
'type' => 'options_select',
))
->save();
entity_get_display('node', 'article', 'default')
->setComponent($this->fieldName, array(
'type' => 'entity_reference_label',
))
->save();
}
/**
* Tests that terms added to nodes are displayed in core RSS feed.
*
* Create a node and assert that taxonomy terms appear in rss.xml.
*/
function testTaxonomyRss() {
// Create two taxonomy terms.
$term1 = $this->createTerm($this->vocabulary);
// RSS display must be added manually.
$this->drupalGet("admin/structure/types/manage/article/display");
$edit = array(
"display_modes_custom[rss]" => '1',
);
$this->drupalPostForm(NULL, $edit, t('Save'));
// Change the format to 'RSS category'.
$this->drupalGet("admin/structure/types/manage/article/display/rss");
$edit = array(
"fields[taxonomy_" . $this->vocabulary->id() . "][type]" => 'entity_reference_rss_category',
);
$this->drupalPostForm(NULL, $edit, t('Save'));
// Post an article.
$edit = array();
$edit['title[0][value]'] = $this->randomMachineName();
$edit[$this->fieldName . '[]'] = $term1->id();
$this->drupalPostForm('node/add/article', $edit, t('Save'));
// Check that the term is displayed when the RSS feed is viewed.
$this->drupalGet('rss.xml');
$test_element = sprintf(
'<category %s>%s</category>',
'domain="' . $term1->url('canonical', array('absolute' => TRUE)) . '"',
$term1->getName()
);
$this->assertRaw($test_element, 'Term is displayed when viewing the rss feed.');
// Test that the feed icon exists for the term.
$this->drupalGet("taxonomy/term/{$term1->id()}");
$this->assertLinkByHref("taxonomy/term/{$term1->id()}/feed");
// Test that the feed page exists for the term.
$this->drupalGet("taxonomy/term/{$term1->id()}/feed");
$this->assertTrue(!empty($this->cssSelect('rss[version="2.0"]')), "Feed page is RSS.");
// Check that the "Exception value" is disabled by default.
$this->drupalGet('taxonomy/term/all/feed');
$this->assertResponse(404);
// Set the exception value to 'all'.
$view = Views::getView('taxonomy_term');
$arguments = $view->getDisplay()->getOption('arguments');
$arguments['tid']['exception']['value'] = 'all';
$view->getDisplay()->overrideOption('arguments', $arguments);
$view->storage->save();
// Check the article is shown in the feed.
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$raw_xml = '<title>' . $node->label() . '</title>';
$this->drupalGet('taxonomy/term/all/feed');
$this->assertRaw($raw_xml, "Raw text '$raw_xml' is found.");
// Unpublish the article and check that it is not shown in the feed.
$node->setPublished(FALSE)->save();
$this->drupalGet('taxonomy/term/all/feed');
$this->assertNoRaw($raw_xml);
}
}

View file

@ -0,0 +1,97 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\field\Entity\FieldConfig;
use Drupal\user\RoleInterface;
use Drupal\file\Entity\File;
use Drupal\field\Entity\FieldStorageConfig;
/**
* Tests access checks of private image fields.
*
* @group taxonomy
*/
class TaxonomyImageTest extends TaxonomyTestBase {
/**
* Used taxonomy vocabulary.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('image');
protected function setUp() {
parent::setUp();
// Remove access content permission from registered users.
user_role_revoke_permissions(RoleInterface::AUTHENTICATED_ID, array('access content'));
$this->vocabulary = $this->createVocabulary();
// Add a field to the vocabulary.
$entity_type = 'taxonomy_term';
$name = 'field_test';
FieldStorageConfig::create(array(
'field_name' => $name,
'entity_type' => $entity_type,
'type' => 'image',
'settings' => array(
'uri_scheme' => 'private',
),
))->save();
FieldConfig::create([
'field_name' => $name,
'entity_type' => $entity_type,
'bundle' => $this->vocabulary->id(),
'settings' => array(),
])->save();
entity_get_display($entity_type, $this->vocabulary->id(), 'default')
->setComponent($name, array(
'type' => 'image',
'settings' => array(),
))
->save();
entity_get_form_display($entity_type, $this->vocabulary->id(), 'default')
->setComponent($name, array(
'type' => 'image_image',
'settings' => array(),
))
->save();
}
public function testTaxonomyImageAccess() {
$user = $this->drupalCreateUser(array('administer site configuration', 'administer taxonomy', 'access user profiles'));
$this->drupalLogin($user);
// Create a term and upload the image.
$files = $this->drupalGetTestFiles('image');
$image = array_pop($files);
$edit['name[0][value]'] = $this->randomMachineName();
$edit['files[field_test_0]'] = drupal_realpath($image->uri);
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add', $edit, t('Save'));
$this->drupalPostForm(NULL, ['field_test[0][alt]' => $this->randomMachineName()], t('Save'));
$terms = entity_load_multiple_by_properties('taxonomy_term', array('name' => $edit['name[0][value]']));
$term = reset($terms);
$this->assertText(t('Created new term @name.', array('@name' => $term->getName())));
// Create a user that should have access to the file and one that doesn't.
$access_user = $this->drupalCreateUser(array('access content'));
$no_access_user = $this->drupalCreateUser();
$image = File::load($term->field_test->target_id);
$this->drupalLogin($access_user);
$this->drupalGet(file_create_url($image->getFileUri()));
$this->assertResponse(200, 'Private image on term is accessible with right permission');
$this->drupalLogin($no_access_user);
$this->drupalGet(file_create_url($image->getFileUri()));
$this->assertResponse(403, 'Private image on term not accessible without right permission');
}
}

View file

@ -0,0 +1,119 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests that appropriate query tags are added.
*
* @group taxonomy
*/
class TaxonomyQueryAlterTest extends WebTestBase {
use TaxonomyTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['taxonomy', 'taxonomy_test'];
/**
* Tests that appropriate tags are added when querying the database.
*/
public function testTaxonomyQueryAlter() {
// Create a new vocabulary and add a few terms to it.
$vocabulary = $this->createVocabulary();
$terms = array();
for ($i = 0; $i < 5; $i++) {
$terms[$i] = $this->createTerm($vocabulary);
}
// Set up hierarchy. Term 2 is a child of 1.
$terms[2]->parent = $terms[1]->id();
$terms[2]->save();
$term_storage = \Drupal::entityManager()->getStorage('taxonomy_term');
$this->setupQueryTagTestHooks();
$loaded_term = $term_storage->load($terms[0]->id());
$this->assertEqual($loaded_term->id(), $terms[0]->id(), 'First term was loaded');
$this->assertQueryTagTestResult(1, 0, 'TermStorage::load()');
$this->setupQueryTagTestHooks();
$loaded_terms = $term_storage->loadTree($vocabulary->id());
$this->assertEqual(count($loaded_terms), count($terms), 'All terms were loaded');
$this->assertQueryTagTestResult(1, 1, 'TermStorage::loadTree()');
$this->setupQueryTagTestHooks();
$loaded_terms = $term_storage->loadParents($terms[2]->id());
$this->assertEqual(count($loaded_terms), 1, 'All parent terms were loaded');
$this->assertQueryTagTestResult(2, 1, 'TermStorage::loadParents()');
$this->setupQueryTagTestHooks();
$loaded_terms = $term_storage->loadChildren($terms[1]->id());
$this->assertEqual(count($loaded_terms), 1, 'All child terms were loaded');
$this->assertQueryTagTestResult(2, 1, 'TermStorage::loadChildren()');
$this->setupQueryTagTestHooks();
$query = db_select('taxonomy_term_data', 't');
$query->addField('t', 'tid');
$query->addTag('taxonomy_term_access');
$tids = $query->execute()->fetchCol();
$this->assertEqual(count($tids), count($terms), 'All term IDs were retrieved');
$this->assertQueryTagTestResult(1, 1, 'custom db_select() with taxonomy_term_access tag (preferred)');
$this->setupQueryTagTestHooks();
$query = db_select('taxonomy_term_data', 't');
$query->addField('t', 'tid');
$query->addTag('term_access');
$tids = $query->execute()->fetchCol();
$this->assertEqual(count($tids), count($terms), 'All term IDs were retrieved');
$this->assertQueryTagTestResult(1, 1, 'custom db_select() with term_access tag (deprecated)');
$this->setupQueryTagTestHooks();
$query = \Drupal::entityQuery('taxonomy_term');
$query->addTag('taxonomy_term_access');
$result = $query->execute();
$this->assertEqual(count($result), count($terms), 'All term IDs were retrieved');
$this->assertQueryTagTestResult(1, 1, 'custom EntityFieldQuery with taxonomy_term_access tag (preferred)');
$this->setupQueryTagTestHooks();
$query = \Drupal::entityQuery('taxonomy_term');
$query->addTag('term_access');
$result = $query->execute();
$this->assertEqual(count($result), count($terms), 'All term IDs were retrieved');
$this->assertQueryTagTestResult(1, 1, 'custom EntityFieldQuery with term_access tag (deprecated)');
}
/**
* Sets up the hooks in the test module.
*/
protected function setupQueryTagTestHooks() {
taxonomy_terms_static_reset();
\Drupal::state()->set('taxonomy_test_query_alter', 0);
\Drupal::state()->set('taxonomy_test_query_term_access_alter', 0);
\Drupal::state()->set('taxonomy_test_query_taxonomy_term_access_alter', 0);
}
/**
* Verifies invocation of the hooks in the test module.
*
* @param int $expected_generic_invocations
* The number of times the generic query_alter hook is expected to have
* been invoked.
* @param int $expected_specific_invocations
* The number of times the tag-specific query_alter hooks are expected to
* have been invoked.
* @param string $method
* A string describing the invoked function which generated the query.
*/
protected function assertQueryTagTestResult($expected_generic_invocations, $expected_specific_invocations, $method) {
$this->assertIdentical($expected_generic_invocations, \Drupal::state()->get('taxonomy_test_query_alter'), 'hook_query_alter() invoked when executing ' . $method);
$this->assertIdentical($expected_specific_invocations, \Drupal::state()->get('taxonomy_test_query_term_access_alter'), 'Deprecated hook_query_term_access_alter() invoked when executing ' . $method);
$this->assertIdentical($expected_specific_invocations, \Drupal::state()->get('taxonomy_test_query_taxonomy_term_access_alter'), 'Preferred hook_query_taxonomy_term_access_alter() invoked when executing ' . $method);
}
}

View file

@ -0,0 +1,78 @@
<?php
namespace Drupal\taxonomy\Tests;
/**
* Ensure that the term indentation works properly.
*
* @group taxonomy
*/
class TaxonomyTermIndentationTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('taxonomy');
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'bypass node access']));
$this->vocabulary = $this->createVocabulary();
}
/**
* Tests term indentation.
*/
function testTermIndentation() {
// Create three taxonomy terms.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
$term3 = $this->createTerm($this->vocabulary);
// Get the taxonomy storage.
$taxonomy_storage = $this->container->get('entity.manager')->getStorage('taxonomy_term');
// Indent the second term under the first one.
$edit = array(
'terms[tid:' . $term2->id() . ':0][term][tid]' => 2,
'terms[tid:' . $term2->id() . ':0][term][parent]' => 1,
'terms[tid:' . $term2->id() . ':0][term][depth]' => 1,
'terms[tid:' . $term2->id() . ':0][weight]' => 1,
);
// Submit the edited form and check for HTML indentation element presence.
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->get('vid') . '/overview', $edit, t('Save'));
$this->assertPattern('|<div class="js-indentation indentation">&nbsp;</div>|');
// Check explicitly that term 2's parent is term 1.
$parents = $taxonomy_storage->loadParents($term2->id());
$this->assertEqual(key($parents), 1, 'Term 1 is the term 2\'s parent');
// Move the second term back out to the root level.
$edit = array(
'terms[tid:' . $term2->id() . ':0][term][tid]' => 2,
'terms[tid:' . $term2->id() . ':0][term][parent]' => 0,
'terms[tid:' . $term2->id() . ':0][term][depth]' => 0,
'terms[tid:' . $term2->id() . ':0][weight]' => 1,
);
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->get('vid' ) . '/overview', $edit, t('Save'));
// All terms back at the root level, no indentation should be present.
$this->assertNoPattern('|<div class="js-indentation indentation">&nbsp;</div>|');
// Check explicitly that term 2 has no parents.
\Drupal::entityManager()->getStorage('taxonomy_term')->resetCache();
$parents = $taxonomy_storage->loadParents($term2->id());
$this->assertTrue(empty($parents), 'Term 2 has no parents now');
}
}

View file

@ -0,0 +1,67 @@
<?php
namespace Drupal\taxonomy\Tests;
/**
* Ensures that the term pager works properly.
*
* @group taxonomy
*/
class TaxonomyTermPagerTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['taxonomy'];
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'bypass node access']));
$this->vocabulary = $this->createVocabulary();
}
/**
* Tests that the pager is displayed properly on the term overview page.
*/
public function testTaxonomyTermOverviewPager() {
// Set limit to 3 terms per page.
$this->config('taxonomy.settings')
->set('terms_per_page_admin', '3')
->save();
// Create 3 terms.
for ($x = 1; $x <= 3; $x++) {
$this->createTerm($this->vocabulary);
}
// Get Page 1.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->assertNoPattern('|<nav class="pager" [^>]*>|', 'Pager is not visible on page 1');
// Create 3 more terms to show pager.
for ($x = 1; $x <= 3; $x++) {
$this->createTerm($this->vocabulary);
}
// Get Page 1.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->assertPattern('|<nav class="pager" [^>]*>|', 'Pager is visible on page 1');
// Get Page 2.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview', ['query' => ['page' => 1]]);
$this->assertPattern('|<nav class="pager" [^>]*>|', 'Pager is visible on page 2');
}
}

View file

@ -0,0 +1,36 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\simpletest\WebTestBase;
/**
* Provides common helper methods for Taxonomy module tests.
*/
abstract class TaxonomyTestBase extends WebTestBase {
use TaxonomyTestTrait;
use EntityReferenceTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('taxonomy', 'block');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('system_breadcrumb_block');
// Create Basic page and Article node types.
if ($this->profile != 'standard') {
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
}
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Language\LanguageInterface;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\Entity\Term;
/**
* Provides common helper methods for Taxonomy module tests.
*/
trait TaxonomyTestTrait {
/**
* Returns a new vocabulary with random properties.
*/
function createVocabulary() {
// Create a vocabulary.
$vocabulary = Vocabulary::create([
'name' => $this->randomMachineName(),
'description' => $this->randomMachineName(),
'vid' => Unicode::strtolower($this->randomMachineName()),
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
'weight' => mt_rand(0, 10),
]);
$vocabulary->save();
return $vocabulary;
}
/**
* Returns a new term with random properties in vocabulary $vid.
*
* @param \Drupal\taxonomy\Entity\Vocabulary $vocabulary
* The vocabulary object.
* @param array $values
* (optional) An array of values to set, keyed by property name. If the
* entity type has bundles, the bundle key has to be specified.
*
* @return \Drupal\taxonomy\Entity\Term
* The new taxonomy term object.
*/
function createTerm(Vocabulary $vocabulary, $values = array()) {
$filter_formats = filter_formats();
$format = array_pop($filter_formats);
$term = Term::create($values + [
'name' => $this->randomMachineName(),
'description' => [
'value' => $this->randomMachineName(),
// Use the first available text format.
'format' => $format->id(),
],
'vid' => $vocabulary->id(),
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
]);
$term->save();
return $term;
}
}

View file

@ -0,0 +1,105 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\language\Entity\ConfigurableLanguage;
/**
* Provides common testing base for translated taxonomy terms.
*/
trait TaxonomyTranslationTestTrait {
use EntityReferenceTestTrait;
/**
* The vocabulary.
*
* @var \Drupal\taxonomy\Entity\Vocabulary;
*/
protected $vocabulary;
/**
* The field name for our taxonomy term field.
*
* @var string
*/
protected $termFieldName = 'field_tag';
/**
* The langcode of the source language.
*
* @var string
*/
protected $baseLangcode = 'en';
/**
* Target langcode for translation.
*
* @var string
*/
protected $translateToLangcode = 'hu';
/**
* The node to check the translated value on.
*
* @var \Drupal\node\Entity\Node
*/
protected $node;
/**
* Adds additional languages.
*/
protected function setupLanguages() {
ConfigurableLanguage::createFromLangcode($this->translateToLangcode)->save();
$this->rebuildContainer();
}
/**
* Enables translations where it needed.
*/
protected function enableTranslation() {
// Enable translation for the current entity type and ensure the change is
// picked up.
\Drupal::service('content_translation.manager')->setEnabled('node', 'article', TRUE);
\Drupal::service('content_translation.manager')->setEnabled('taxonomy_term', $this->vocabulary->id(), TRUE);
drupal_static_reset();
\Drupal::entityManager()->clearCachedDefinitions();
\Drupal::service('router.builder')->rebuild();
\Drupal::service('entity.definition_update_manager')->applyUpdates();
}
/**
* Adds term reference field for the article content type.
*
* @param bool $translatable
* (optional) If TRUE, create a translatable term reference field. Defaults
* to FALSE.
*/
protected function setUpTermReferenceField() {
$handler_settings = array(
'target_bundles' => array(
$this->vocabulary->id() => $this->vocabulary->id(),
),
'auto_create' => TRUE,
);
$this->createEntityReferenceField('node', 'article', $this->termFieldName, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
$field_storage = FieldStorageConfig::loadByName('node', $this->termFieldName);
$field_storage->setTranslatable(FALSE);
$field_storage->save();
entity_get_form_display('node', 'article', 'default')
->setComponent($this->termFieldName, array(
'type' => 'entity_reference_autocomplete_tags',
))
->save();
entity_get_display('node', 'article', 'default')
->setComponent($this->termFieldName, array(
'type' => 'entity_reference_label',
))
->save();
}
}

View file

@ -0,0 +1,204 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
/**
* Tests the autocomplete implementation of the taxonomy class.
*
* @group taxonomy
*/
class TermAutocompleteTest extends TaxonomyTestBase {
/**
* The vocabulary.
*
* @var \Drupal\taxonomy\Entity\Vocabulary
*/
protected $vocabulary;
/**
* The field to add to the content type for the taxonomy terms.
*
* @var string
*/
protected $fieldName;
/**
* The admin user.
*
* @var \Drupal\user\Entity\User
*/
protected $adminUser;
/**
* The autocomplete URL to call.
*
* @var string
*/
protected $autocompleteUrl;
/**
* The term IDs indexed by term names.
*
* @var array
*/
protected $termIds;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create a vocabulary.
$this->vocabulary = $this->createVocabulary();
// Create 11 terms, which have some sub-string in common, in a
// non-alphabetical order, so that we will have more than 10 matches later
// when we test the correct number of results is returned, and we can test
// the order of the results. The location of the sub-string to match varies
// also, since it should not be necessary to start with the sub-string to
// match it. Save term IDs to reuse later.
$termNames = [
'aaa 20 bbb',
'aaa 70 bbb',
'aaa 10 bbb',
'aaa 12 bbb',
'aaa 40 bbb',
'aaa 11 bbb',
'aaa 30 bbb',
'aaa 50 bbb',
'aaa 80',
'aaa 90',
'bbb 60 aaa',
];
foreach ($termNames as $termName) {
$term = $this->createTerm($this->vocabulary, ['name' => $termName]);
$this->termIds[$termName] = $term->id();
}
// Create a taxonomy_term_reference field on the article Content Type that
// uses a taxonomy_autocomplete widget.
$this->fieldName = Unicode::strtolower($this->randomMachineName());
FieldStorageConfig::create([
'field_name' => $this->fieldName,
'entity_type' => 'node',
'type' => 'entity_reference',
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
'settings' => [
'target_type' => 'taxonomy_term',
],
])->save();
FieldConfig::create([
'field_name' => $this->fieldName,
'bundle' => 'article',
'entity_type' => 'node',
'settings' => [
'handler' => 'default',
'handler_settings' => [
// Restrict selection of terms to a single vocabulary.
'target_bundles' => [
$this->vocabulary->id() => $this->vocabulary->id(),
],
],
],
])->save();
EntityFormDisplay::load('node.article.default')
->setComponent($this->fieldName, [
'type' => 'entity_reference_autocomplete',
])
->save();
EntityViewDisplay::load('node.article.default')
->setComponent($this->fieldName, [
'type' => 'entity_reference_label',
])
->save();
// Create a user and then login.
$this->adminUser = $this->drupalCreateUser(['create article content']);
$this->drupalLogin($this->adminUser);
// Retrieve the autocomplete url.
$this->drupalGet('node/add/article');
$result = $this->xpath('//input[@name="' . $this->fieldName . '[0][target_id]"]');
$this->autocompleteUrl = $this->getAbsoluteUrl($result[0]['data-autocomplete-path']);
}
/**
* Tests that the autocomplete method returns the good number of results.
*
* @see \Drupal\taxonomy\Controller\TermAutocompleteController::autocomplete()
*/
public function testAutocompleteCountResults() {
// Test that no matching term found.
$data = $this->drupalGetJSON(
$this->autocompleteUrl,
['query' => ['q' => 'zzz']]
);
$this->assertTrue(empty($data), 'Autocomplete returned no results');
// Test that only one matching term found, when only one matches.
$data = $this->drupalGetJSON(
$this->autocompleteUrl,
['query' => ['q' => 'aaa 10']]
);
$this->assertEqual(1, count($data), 'Autocomplete returned 1 result');
// Test the correct number of matches when multiple are partial matches.
$data = $this->drupalGetJSON(
$this->autocompleteUrl,
['query' => ['q' => 'aaa 1']]
);
$this->assertEqual(3, count($data), 'Autocomplete returned 3 results');
// Tests that only 10 results are returned, even if there are more than 10
// matches.
$data = $this->drupalGetJSON(
$this->autocompleteUrl,
['query' => ['q' => 'aaa']]
);
$this->assertEqual(10, count($data), 'Autocomplete returned only 10 results (for over 10 matches)');
}
/**
* Tests that the autocomplete method returns properly ordered results.
*
* @see \Drupal\taxonomy\Controller\TermAutocompleteController::autocomplete()
*/
public function testAutocompleteOrderedResults() {
$expectedResults = [
'aaa 10 bbb',
'aaa 11 bbb',
'aaa 12 bbb',
'aaa 20 bbb',
'aaa 30 bbb',
'aaa 40 bbb',
'aaa 50 bbb',
'aaa 70 bbb',
'bbb 60 aaa',
];
// Build $expected to match the autocomplete results.
$expected = [];
foreach ($expectedResults as $termName) {
$expected[] = [
'value' => $termName . ' (' . $this->termIds[$termName] . ')',
'label' => $termName
];
}
$data = $this->drupalGetJSON(
$this->autocompleteUrl,
['query' => ['q' => 'bbb']]
);
$this->assertIdentical($expected, $data);
}
}

View file

@ -0,0 +1,42 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\system\Tests\Entity\EntityWithUriCacheTagsTestBase;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\Entity\Term;
/**
* Tests the Taxonomy term entity's cache tags.
*
* @group taxonomy
*/
class TermCacheTagsTest extends EntityWithUriCacheTagsTestBase {
/**
* {@inheritdoc}
*/
public static $modules = array('taxonomy');
/**
* {@inheritdoc}
*/
protected function createEntity() {
// Create a "Camelids" vocabulary.
$vocabulary = Vocabulary::create([
'name' => 'Camelids',
'vid' => 'camelids',
]);
$vocabulary->save();
// Create a "Llama" taxonomy term.
$term = Term::create([
'name' => 'Llama',
'vid' => $vocabulary->id(),
]);
$term->save();
return $term;
}
}

View file

@ -0,0 +1,79 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;
/**
* Tests the settings of restricting term selection to a single vocabulary.
*
* @group taxonomy
*/
class TermEntityReferenceTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['entity_reference_test', 'entity_test'];
/**
* Tests an entity reference field restricted to a single vocabulary.
*
* Creates two vocabularies with a term, then set up the entity reference
* field to limit the target vocabulary to one of them, ensuring that
* the restriction applies.
*/
function testSelectionTestVocabularyRestriction() {
// Create two vocabularies.
$vocabulary = $this->createVocabulary();
$vocabulary2 = $this->createVocabulary();
$term = $this->createTerm($vocabulary);
$term2 = $this->createTerm($vocabulary2);
// Create an entity reference field.
$field_name = 'taxonomy_' . $vocabulary->id();
$field_storage = FieldStorageConfig::create(array(
'field_name' => $field_name,
'entity_type' => 'entity_test',
'translatable' => FALSE,
'settings' => array(
'target_type' => 'taxonomy_term',
),
'type' => 'entity_reference',
'cardinality' => 1,
));
$field_storage->save();
$field = FieldConfig::create(array(
'field_storage' => $field_storage,
'entity_type' => 'entity_test',
'bundle' => 'test_bundle',
'settings' => array(
'handler' => 'default',
'handler_settings' => array(
// Restrict selection of terms to a single vocabulary.
'target_bundles' => array(
$vocabulary->id() => $vocabulary->id(),
),
),
),
));
$field->save();
$handler = $this->container->get('plugin.manager.entity_reference_selection')->getSelectionHandler($field);
$result = $handler->getReferenceableEntities();
$expected_result = array(
$vocabulary->id() => array(
$term->id() => $term->getName(),
),
);
$this->assertIdentical($result, $expected_result, 'Terms selection restricted to a single vocabulary.');
}
}

View file

@ -0,0 +1,214 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
/**
* Tests the hook implementations that maintain the taxonomy index.
*
* @group taxonomy
*/
class TermIndexTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('views');
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* Name of the taxonomy term reference field.
*
* @var string
*/
protected $fieldName1;
/**
* Name of the taxonomy term reference field.
*
* @var string
*/
protected $fieldName2;
protected function setUp() {
parent::setUp();
// Create an administrative user.
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'bypass node access']));
// Create a vocabulary and add two term reference fields to article nodes.
$this->vocabulary = $this->createVocabulary();
$this->fieldName1 = Unicode::strtolower($this->randomMachineName());
$handler_settings = array(
'target_bundles' => array(
$this->vocabulary->id() => $this->vocabulary->id(),
),
'auto_create' => TRUE,
);
$this->createEntityReferenceField('node', 'article', $this->fieldName1, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
entity_get_form_display('node', 'article', 'default')
->setComponent($this->fieldName1, array(
'type' => 'options_select',
))
->save();
entity_get_display('node', 'article', 'default')
->setComponent($this->fieldName1, array(
'type' => 'entity_reference_label',
))
->save();
$this->fieldName2 = Unicode::strtolower($this->randomMachineName());
$this->createEntityReferenceField('node', 'article', $this->fieldName2, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
entity_get_form_display('node', 'article', 'default')
->setComponent($this->fieldName2, array(
'type' => 'options_select',
))
->save();
entity_get_display('node', 'article', 'default')
->setComponent($this->fieldName2, array(
'type' => 'entity_reference_label',
))
->save();
}
/**
* Tests that the taxonomy index is maintained properly.
*/
function testTaxonomyIndex() {
$node_storage = $this->container->get('entity.manager')->getStorage('node');
// Create terms in the vocabulary.
$term_1 = $this->createTerm($this->vocabulary);
$term_2 = $this->createTerm($this->vocabulary);
// Post an article.
$edit = array();
$edit['title[0][value]'] = $this->randomMachineName();
$edit['body[0][value]'] = $this->randomMachineName();
$edit["{$this->fieldName1}[]"] = $term_1->id();
$edit["{$this->fieldName2}[]"] = $term_1->id();
$this->drupalPostForm('node/add/article', $edit, t('Save'));
// Check that the term is indexed, and only once.
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
':nid' => $node->id(),
':tid' => $term_1->id(),
))->fetchField();
$this->assertEqual(1, $index_count, 'Term 1 is indexed once.');
// Update the article to change one term.
$edit["{$this->fieldName1}[]"] = $term_2->id();
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
// Check that both terms are indexed.
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
':nid' => $node->id(),
':tid' => $term_1->id(),
))->fetchField();
$this->assertEqual(1, $index_count, 'Term 1 is indexed.');
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
':nid' => $node->id(),
':tid' => $term_2->id(),
))->fetchField();
$this->assertEqual(1, $index_count, 'Term 2 is indexed.');
// Update the article to change another term.
$edit["{$this->fieldName2}[]"] = $term_2->id();
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
// Check that only one term is indexed.
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
':nid' => $node->id(),
':tid' => $term_1->id(),
))->fetchField();
$this->assertEqual(0, $index_count, 'Term 1 is not indexed.');
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
':nid' => $node->id(),
':tid' => $term_2->id(),
))->fetchField();
$this->assertEqual(1, $index_count, 'Term 2 is indexed once.');
// Redo the above tests without interface.
$node_storage->resetCache(array($node->id()));
$node = $node_storage->load($node->id());
$node->title = $this->randomMachineName();
// Update the article with no term changed.
$node->save();
// Check that the index was not changed.
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
':nid' => $node->id(),
':tid' => $term_1->id(),
))->fetchField();
$this->assertEqual(0, $index_count, 'Term 1 is not indexed.');
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
':nid' => $node->id(),
':tid' => $term_2->id(),
))->fetchField();
$this->assertEqual(1, $index_count, 'Term 2 is indexed once.');
// Update the article to change one term.
$node->{$this->fieldName1} = array(array('target_id' => $term_1->id()));
$node->save();
// Check that both terms are indexed.
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
':nid' => $node->id(),
':tid' => $term_1->id(),
))->fetchField();
$this->assertEqual(1, $index_count, 'Term 1 is indexed.');
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
':nid' => $node->id(),
':tid' => $term_2->id(),
))->fetchField();
$this->assertEqual(1, $index_count, 'Term 2 is indexed.');
// Update the article to change another term.
$node->{$this->fieldName2} = array(array('target_id' => $term_1->id()));
$node->save();
// Check that only one term is indexed.
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
':nid' => $node->id(),
':tid' => $term_1->id(),
))->fetchField();
$this->assertEqual(1, $index_count, 'Term 1 is indexed once.');
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', array(
':nid' => $node->id(),
':tid' => $term_2->id(),
))->fetchField();
$this->assertEqual(0, $index_count, 'Term 2 is not indexed.');
}
/**
* Tests that there is a link to the parent term on the child term page.
*/
function testTaxonomyTermHierarchyBreadcrumbs() {
// Create two taxonomy terms and set term2 as the parent of term1.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
$term1->parent = array($term2->id());
$term1->save();
// Verify that the page breadcrumbs include a link to the parent term.
$this->drupalGet('taxonomy/term/' . $term1->id());
// Breadcrumbs are not rendered with a language, prevent the term
// language from being added to the options.
$this->assertRaw(\Drupal::l($term2->getName(), $term2->urlInfo('canonical', ['language' => NULL])), 'Parent term link is displayed when viewing the node.');
}
}

View file

@ -0,0 +1,110 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Core\Language\LanguageInterface;
use Drupal\language\Entity\ConfigurableLanguage;
/**
* Tests the language functionality for the taxonomy terms.
*
* @group taxonomy
*/
class TermLanguageTest extends TaxonomyTestBase {
public static $modules = array('language');
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
protected function setUp() {
parent::setUp();
// Create an administrative user.
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy']));
// Create a vocabulary to which the terms will be assigned.
$this->vocabulary = $this->createVocabulary();
// Add some custom languages.
foreach (array('aa', 'bb', 'cc') as $language_code) {
ConfigurableLanguage::create(array(
'id' => $language_code,
'label' => $this->randomMachineName(),
))->save();
}
}
function testTermLanguage() {
// Configure the vocabulary to not hide the language selector.
$edit = array(
'default_language[language_alterable]' => TRUE,
);
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
// Add a term.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
// Check that we have the language selector.
$this->assertField('edit-langcode-0-value', t('The language selector field was found on the page.'));
// Submit the term.
$edit = array(
'name[0][value]' => $this->randomMachineName(),
'langcode[0][value]' => 'aa',
);
$this->drupalPostForm(NULL, $edit, t('Save'));
$terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']);
$term = reset($terms);
$this->assertEqual($term->language()->getId(), $edit['langcode[0][value]'], 'The term contains the correct langcode.');
// Check if on the edit page the language is correct.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$this->assertOptionSelected('edit-langcode-0-value', $edit['langcode[0][value]'], 'The term language was correctly selected.');
// Change the language of the term.
$edit['langcode[0][value]'] = 'bb';
$this->drupalPostForm('taxonomy/term/' . $term->id() . '/edit', $edit, t('Save'));
// Check again that on the edit page the language is correct.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$this->assertOptionSelected('edit-langcode-0-value', $edit['langcode[0][value]'], 'The term language was correctly selected.');
}
function testDefaultTermLanguage() {
// Configure the vocabulary to not hide the language selector, and make the
// default language of the terms fixed.
$edit = array(
'default_language[langcode]' => 'bb',
'default_language[language_alterable]' => TRUE,
);
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
$this->assertOptionSelected('edit-langcode-0-value', 'bb', 'The expected langcode was selected.');
// Make the default language of the terms to be the current interface.
$edit = array(
'default_language[langcode]' => 'current_interface',
'default_language[language_alterable]' => TRUE,
);
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
$this->drupalGet('aa/admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
$this->assertOptionSelected('edit-langcode-0-value', 'aa', "The expected langcode, 'aa', was selected.");
$this->drupalGet('bb/admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
$this->assertOptionSelected('edit-langcode-0-value', 'bb', "The expected langcode, 'bb', was selected.");
// Change the default language of the site and check if the default terms
// language is still correctly selected.
$this->config('system.site')->set('default_langcode', 'cc')->save();
$edit = array(
'default_language[langcode]' => LanguageInterface::LANGCODE_SITE_DEFAULT,
'default_language[language_alterable]' => TRUE,
);
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
$this->assertOptionSelected('edit-langcode-0-value', 'cc', "The expected langcode, 'cc', was selected.");
}
}

View file

@ -0,0 +1,588 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Component\Utility\Tags;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
/**
* Tests load, save and delete for taxonomy terms.
*
* @group taxonomy
*/
class TermTest extends TaxonomyTestBase {
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* Taxonomy term reference field for testing.
*
* @var \Drupal\field\FieldConfigInterface
*/
protected $field;
/**
* Modules to enable.
*
* @var string[]
*/
public static $modules = ['block'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('local_actions_block');
$this->drupalPlaceBlock('local_tasks_block');
$this->drupalPlaceBlock('page_title_block');
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'bypass node access']));
$this->vocabulary = $this->createVocabulary();
$field_name = 'taxonomy_' . $this->vocabulary->id();
$handler_settings = array(
'target_bundles' => array(
$this->vocabulary->id() => $this->vocabulary->id(),
),
'auto_create' => TRUE,
);
$this->createEntityReferenceField('node', 'article', $field_name, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
$this->field = FieldConfig::loadByName('node', 'article', $field_name);
entity_get_form_display('node', 'article', 'default')
->setComponent($field_name, array(
'type' => 'options_select',
))
->save();
entity_get_display('node', 'article', 'default')
->setComponent($field_name, array(
'type' => 'entity_reference_label',
))
->save();
}
/**
* Test terms in a single and multiple hierarchy.
*/
function testTaxonomyTermHierarchy() {
// Create two taxonomy terms.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
// Get the taxonomy storage.
$taxonomy_storage = $this->container->get('entity.manager')->getStorage('taxonomy_term');
// Check that hierarchy is flat.
$vocabulary = Vocabulary::load($this->vocabulary->id());
$this->assertEqual(0, $vocabulary->getHierarchy(), 'Vocabulary is flat.');
// Edit $term2, setting $term1 as parent.
$edit = array();
$edit['parent[]'] = array($term1->id());
$this->drupalPostForm('taxonomy/term/' . $term2->id() . '/edit', $edit, t('Save'));
// Check the hierarchy.
$children = $taxonomy_storage->loadChildren($term1->id());
$parents = $taxonomy_storage->loadParents($term2->id());
$this->assertTrue(isset($children[$term2->id()]), 'Child found correctly.');
$this->assertTrue(isset($parents[$term1->id()]), 'Parent found correctly.');
// Load and save a term, confirming that parents are still set.
$term = Term::load($term2->id());
$term->save();
$parents = $taxonomy_storage->loadParents($term2->id());
$this->assertTrue(isset($parents[$term1->id()]), 'Parent found correctly.');
// Create a third term and save this as a parent of term2.
$term3 = $this->createTerm($this->vocabulary);
$term2->parent = array($term1->id(), $term3->id());
$term2->save();
$parents = $taxonomy_storage->loadParents($term2->id());
$this->assertTrue(isset($parents[$term1->id()]) && isset($parents[$term3->id()]), 'Both parents found successfully.');
}
/**
* Tests that many terms with parents show on each page
*/
function testTaxonomyTermChildTerms() {
// Set limit to 10 terms per page. Set variable to 9 so 10 terms appear.
$this->config('taxonomy.settings')->set('terms_per_page_admin', '9')->save();
$term1 = $this->createTerm($this->vocabulary);
$terms_array = [];
$taxonomy_storage = $this->container->get('entity.manager')->getStorage('taxonomy_term');
// Create 40 terms. Terms 1-12 get parent of $term1. All others are
// individual terms.
for ($x = 1; $x <= 40; $x++) {
$edit = array();
// Set terms in order so we know which terms will be on which pages.
$edit['weight'] = $x;
// Set terms 1-20 to be children of first term created.
if ($x <= 12) {
$edit['parent'] = $term1->id();
}
$term = $this->createTerm($this->vocabulary, $edit);
$children = $taxonomy_storage->loadChildren($term1->id());
$parents = $taxonomy_storage->loadParents($term->id());
$terms_array[$x] = Term::load($term->id());
}
// Get Page 1.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->assertText($term1->getName(), 'Parent Term is displayed on Page 1');
for ($x = 1; $x <= 13; $x++) {
$this->assertText($terms_array[$x]->getName(), $terms_array[$x]->getName() . ' found on Page 1');
}
// Get Page 2.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview', array('query' => array('page' => 1)));
$this->assertText($term1->getName(), 'Parent Term is displayed on Page 2');
for ($x = 1; $x <= 18; $x++) {
$this->assertText($terms_array[$x]->getName(), $terms_array[$x]->getName() . ' found on Page 2');
}
// Get Page 3.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview', array('query' => array('page' => 2)));
$this->assertNoText($term1->getName(), 'Parent Term is not displayed on Page 3');
for ($x = 1; $x <= 17; $x++) {
$this->assertNoText($terms_array[$x]->getName(), $terms_array[$x]->getName() . ' not found on Page 3');
}
for ($x = 18; $x <= 25; $x++) {
$this->assertText($terms_array[$x]->getName(), $terms_array[$x]->getName() . ' found on Page 3');
}
}
/**
* Test that hook_node_$op implementations work correctly.
*
* Save & edit a node and assert that taxonomy terms are saved/loaded properly.
*/
function testTaxonomyNode() {
// Create two taxonomy terms.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
// Post an article.
$edit = array();
$edit['title[0][value]'] = $this->randomMachineName();
$edit['body[0][value]'] = $this->randomMachineName();
$edit[$this->field->getName() . '[]'] = $term1->id();
$this->drupalPostForm('node/add/article', $edit, t('Save'));
// Check that the term is displayed when the node is viewed.
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$this->drupalGet('node/' . $node->id());
$this->assertText($term1->getName(), 'Term is displayed when viewing the node.');
$this->clickLink(t('Edit'));
$this->assertText($term1->getName(), 'Term is displayed when editing the node.');
$this->drupalPostForm(NULL, array(), t('Save'));
$this->assertText($term1->getName(), 'Term is displayed after saving the node with no changes.');
// Edit the node with a different term.
$edit[$this->field->getName() . '[]'] = $term2->id();
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
$this->drupalGet('node/' . $node->id());
$this->assertText($term2->getName(), 'Term is displayed when viewing the node.');
// Preview the node.
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Preview'));
$this->assertUniqueText($term2->getName(), 'Term is displayed when previewing the node.');
$this->drupalPostForm('node/' . $node->id() . '/edit', NULL, t('Preview'));
$this->assertUniqueText($term2->getName(), 'Term is displayed when previewing the node again.');
}
/**
* Test term creation with a free-tagging vocabulary from the node form.
*/
function testNodeTermCreationAndDeletion() {
// Enable tags in the vocabulary.
$field = $this->field;
entity_get_form_display($field->getTargetEntityTypeId(), $field->getTargetBundle(), 'default')
->setComponent($field->getName(), array(
'type' => 'entity_reference_autocomplete_tags',
'settings' => array(
'placeholder' => 'Start typing here.',
),
))
->save();
// Prefix the terms with a letter to ensure there is no clash in the first
// three letters.
// @see https://www.drupal.org/node/2397691
$terms = array(
'term1' => 'a' . $this->randomMachineName(),
'term2' => 'b' . $this->randomMachineName(),
'term3' => 'c' . $this->randomMachineName() . ', ' . $this->randomMachineName(),
'term4' => 'd' . $this->randomMachineName(),
);
$edit = array();
$edit['title[0][value]'] = $this->randomMachineName();
$edit['body[0][value]'] = $this->randomMachineName();
// Insert the terms in a comma separated list. Vocabulary 1 is a
// free-tagging field created by the default profile.
$edit[$field->getName() . '[target_id]'] = Tags::implode($terms);
// Verify the placeholder is there.
$this->drupalGet('node/add/article');
$this->assertRaw('placeholder="Start typing here."', 'Placeholder is present.');
// Preview and verify the terms appear but are not created.
$this->drupalPostForm(NULL, $edit, t('Preview'));
foreach ($terms as $term) {
$this->assertText($term, 'The term appears on the node preview.');
}
$tree = $this->container->get('entity.manager')->getStorage('taxonomy_term')->loadTree($this->vocabulary->id());
$this->assertTrue(empty($tree), 'The terms are not created on preview.');
// taxonomy.module does not maintain its static caches.
taxonomy_terms_static_reset();
// Save, creating the terms.
$this->drupalPostForm('node/add/article', $edit, t('Save'));
$this->assertText(t('@type @title has been created.', array('@type' => t('Article'), '@title' => $edit['title[0][value]'])), 'The node was created successfully.');
// Verify that the creation message contains a link to a node.
$view_link = $this->xpath('//div[@class="messages"]//a[contains(@href, :href)]', array(':href' => 'node/'));
$this->assert(isset($view_link), 'The message area contains a link to a node');
foreach ($terms as $term) {
$this->assertText($term, 'The term was saved and appears on the node page.');
}
// Get the created terms.
$term_objects = array();
foreach ($terms as $key => $term) {
$term_objects[$key] = taxonomy_term_load_multiple_by_name($term);
$term_objects[$key] = reset($term_objects[$key]);
}
// Get the node.
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
// Test editing the node.
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
foreach ($terms as $term) {
$this->assertText($term, 'The term was retained after edit and still appears on the node page.');
}
// Delete term 1 from the term edit page.
$this->drupalGet('taxonomy/term/' . $term_objects['term1']->id() . '/edit');
$this->clickLink(t('Delete'));
$this->drupalPostForm(NULL, NULL, t('Delete'));
// Delete term 2 from the term delete page.
$this->drupalGet('taxonomy/term/' . $term_objects['term2']->id() . '/delete');
$this->drupalPostForm(NULL, array(), t('Delete'));
$term_names = array($term_objects['term3']->getName(), $term_objects['term4']->getName());
$this->drupalGet('node/' . $node->id());
foreach ($term_names as $term_name) {
$this->assertText($term_name, format_string('The term %name appears on the node page after two terms, %deleted1 and %deleted2, were deleted.', array('%name' => $term_name, '%deleted1' => $term_objects['term1']->getName(), '%deleted2' => $term_objects['term2']->getName())));
}
$this->assertNoText($term_objects['term1']->getName(), format_string('The deleted term %name does not appear on the node page.', array('%name' => $term_objects['term1']->getName())));
$this->assertNoText($term_objects['term2']->getName(), format_string('The deleted term %name does not appear on the node page.', array('%name' => $term_objects['term2']->getName())));
}
/**
* Save, edit and delete a term using the user interface.
*/
function testTermInterface() {
\Drupal::service('module_installer')->install(array('views'));
$edit = array(
'name[0][value]' => $this->randomMachineName(12),
'description[0][value]' => $this->randomMachineName(100),
);
// Explicitly set the parents field to 'root', to ensure that
// TermForm::save() handles the invalid term ID correctly.
$edit['parent[]'] = array(0);
// Create the term to edit.
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add', $edit, t('Save'));
$terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']);
$term = reset($terms);
$this->assertNotNull($term, 'Term found in database.');
// Submitting a term takes us to the add page; we need the List page.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->clickLink(t('Edit'));
$this->assertRaw($edit['name[0][value]'], 'The randomly generated term name is present.');
$this->assertText($edit['description[0][value]'], 'The randomly generated term description is present.');
$edit = array(
'name[0][value]' => $this->randomMachineName(14),
'description[0][value]' => $this->randomMachineName(102),
);
// Edit the term.
$this->drupalPostForm('taxonomy/term/' . $term->id() . '/edit', $edit, t('Save'));
// Check that the term is still present at admin UI after edit.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->assertText($edit['name[0][value]'], 'The randomly generated term name is present.');
$this->assertLink(t('Edit'));
// Check the term link can be clicked through to the term page.
$this->clickLink($edit['name[0][value]']);
$this->assertResponse(200, 'Term page can be accessed via the listing link.');
// View the term and check that it is correct.
$this->drupalGet('taxonomy/term/' . $term->id());
$this->assertText($edit['name[0][value]'], 'The randomly generated term name is present.');
$this->assertText($edit['description[0][value]'], 'The randomly generated term description is present.');
// Did this page request display a 'term-listing-heading'?
$this->assertTrue($this->xpath('//div[contains(@class, "field--name-description")]'), 'Term page displayed the term description element.');
// Check that it does NOT show a description when description is blank.
$term->setDescription(NULL);
$term->save();
$this->drupalGet('taxonomy/term/' . $term->id());
$this->assertFalse($this->xpath('//div[contains(@class, "field--entity-taxonomy-term--description")]'), 'Term page did not display the term description when description was blank.');
// Check that the description value is processed.
$value = $this->randomMachineName();
$term->setDescription($value);
$term->save();
$this->assertEqual($term->description->processed, "<p>$value</p>\n");
// Check that the term feed page is working.
$this->drupalGet('taxonomy/term/' . $term->id() . '/feed');
// Delete the term.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$this->clickLink(t('Delete'));
$this->drupalPostForm(NULL, NULL, t('Delete'));
// Assert that the term no longer exists.
$this->drupalGet('taxonomy/term/' . $term->id());
$this->assertResponse(404, 'The taxonomy term page was not found.');
}
/**
* Save, edit and delete a term using the user interface.
*/
function testTermReorder() {
$this->createTerm($this->vocabulary);
$this->createTerm($this->vocabulary);
$this->createTerm($this->vocabulary);
$taxonomy_storage = $this->container->get('entity.manager')->getStorage('taxonomy_term');
// Fetch the created terms in the default alphabetical order, i.e. term1
// precedes term2 alphabetically, and term2 precedes term3.
$taxonomy_storage->resetCache();
list($term1, $term2, $term3) = $taxonomy_storage->loadTree($this->vocabulary->id(), 0, NULL, TRUE);
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
// Each term has four hidden fields, "tid:1:0[tid]", "tid:1:0[parent]",
// "tid:1:0[depth]", and "tid:1:0[weight]". Change the order to term2,
// term3, term1 by setting weight property, make term3 a child of term2 by
// setting the parent and depth properties, and update all hidden fields.
$edit = array(
'terms[tid:' . $term2->id() . ':0][term][tid]' => $term2->id(),
'terms[tid:' . $term2->id() . ':0][term][parent]' => 0,
'terms[tid:' . $term2->id() . ':0][term][depth]' => 0,
'terms[tid:' . $term2->id() . ':0][weight]' => 0,
'terms[tid:' . $term3->id() . ':0][term][tid]' => $term3->id(),
'terms[tid:' . $term3->id() . ':0][term][parent]' => $term2->id(),
'terms[tid:' . $term3->id() . ':0][term][depth]' => 1,
'terms[tid:' . $term3->id() . ':0][weight]' => 1,
'terms[tid:' . $term1->id() . ':0][term][tid]' => $term1->id(),
'terms[tid:' . $term1->id() . ':0][term][parent]' => 0,
'terms[tid:' . $term1->id() . ':0][term][depth]' => 0,
'terms[tid:' . $term1->id() . ':0][weight]' => 2,
);
$this->drupalPostForm(NULL, $edit, t('Save'));
$taxonomy_storage->resetCache();
$terms = $taxonomy_storage->loadTree($this->vocabulary->id());
$this->assertEqual($terms[0]->tid, $term2->id(), 'Term 2 was moved above term 1.');
$this->assertEqual($terms[1]->parents, array($term2->id()), 'Term 3 was made a child of term 2.');
$this->assertEqual($terms[2]->tid, $term1->id(), 'Term 1 was moved below term 2.');
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview', array(), t('Reset to alphabetical'));
// Submit confirmation form.
$this->drupalPostForm(NULL, array(), t('Reset to alphabetical'));
// Ensure form redirected back to overview.
$this->assertUrl('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$taxonomy_storage->resetCache();
$terms = $taxonomy_storage->loadTree($this->vocabulary->id(), 0, NULL, TRUE);
$this->assertEqual($terms[0]->id(), $term1->id(), 'Term 1 was moved to back above term 2.');
$this->assertEqual($terms[1]->id(), $term2->id(), 'Term 2 was moved to back below term 1.');
$this->assertEqual($terms[2]->id(), $term3->id(), 'Term 3 is still below term 2.');
$this->assertEqual($terms[2]->parents, array($term2->id()), 'Term 3 is still a child of term 2.');
}
/**
* Test saving a term with multiple parents through the UI.
*/
function testTermMultipleParentsInterface() {
// Add a new term to the vocabulary so that we can have multiple parents.
$parent = $this->createTerm($this->vocabulary);
// Add a new term with multiple parents.
$edit = array(
'name[0][value]' => $this->randomMachineName(12),
'description[0][value]' => $this->randomMachineName(100),
'parent[]' => array(0, $parent->id()),
);
// Save the new term.
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add', $edit, t('Save'));
// Check that the term was successfully created.
$terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']);
$term = reset($terms);
$this->assertNotNull($term, 'Term found in database.');
$this->assertEqual($edit['name[0][value]'], $term->getName(), 'Term name was successfully saved.');
$this->assertEqual($edit['description[0][value]'], $term->getDescription(), 'Term description was successfully saved.');
// Check that the parent tid is still there. The other parent (<root>) is
// not added by \Drupal\taxonomy\TermStorageInterface::loadParents().
$parents = $this->container->get('entity.manager')->getStorage('taxonomy_term')->loadParents($term->id());
$parent = reset($parents);
$this->assertEqual($edit['parent[]'][1], $parent->id(), 'Term parents were successfully saved.');
}
/**
* Test taxonomy_term_load_multiple_by_name().
*/
function testTaxonomyGetTermByName() {
$term = $this->createTerm($this->vocabulary);
// Load the term with the exact name.
$terms = taxonomy_term_load_multiple_by_name($term->getName());
$this->assertTrue(isset($terms[$term->id()]), 'Term loaded using exact name.');
// Load the term with space concatenated.
$terms = taxonomy_term_load_multiple_by_name(' ' . $term->getName() . ' ');
$this->assertTrue(isset($terms[$term->id()]), 'Term loaded with extra whitespace.');
// Load the term with name uppercased.
$terms = taxonomy_term_load_multiple_by_name(strtoupper($term->getName()));
$this->assertTrue(isset($terms[$term->id()]), 'Term loaded with uppercased name.');
// Load the term with name lowercased.
$terms = taxonomy_term_load_multiple_by_name(strtolower($term->getName()));
$this->assertTrue(isset($terms[$term->id()]), 'Term loaded with lowercased name.');
// Try to load an invalid term name.
$terms = taxonomy_term_load_multiple_by_name('Banana');
$this->assertFalse($terms, 'No term loaded with an invalid name.');
// Try to load the term using a substring of the name.
$terms = taxonomy_term_load_multiple_by_name(Unicode::substr($term->getName(), 2), 'No term loaded with a substring of the name.');
$this->assertFalse($terms);
// Create a new term in a different vocabulary with the same name.
$new_vocabulary = $this->createVocabulary();
$new_term = Term::create([
'name' => $term->getName(),
'vid' => $new_vocabulary->id(),
]);
$new_term->save();
// Load multiple terms with the same name.
$terms = taxonomy_term_load_multiple_by_name($term->getName());
$this->assertEqual(count($terms), 2, 'Two terms loaded with the same name.');
// Load single term when restricted to one vocabulary.
$terms = taxonomy_term_load_multiple_by_name($term->getName(), $this->vocabulary->id());
$this->assertEqual(count($terms), 1, 'One term loaded when restricted by vocabulary.');
$this->assertTrue(isset($terms[$term->id()]), 'Term loaded using exact name and vocabulary machine name.');
// Create a new term with another name.
$term2 = $this->createTerm($this->vocabulary);
// Try to load a term by name that doesn't exist in this vocabulary but
// exists in another vocabulary.
$terms = taxonomy_term_load_multiple_by_name($term2->getName(), $new_vocabulary->id());
$this->assertFalse($terms, 'Invalid term name restricted by vocabulary machine name not loaded.');
// Try to load terms filtering by a non-existing vocabulary.
$terms = taxonomy_term_load_multiple_by_name($term2->getName(), 'non_existing_vocabulary');
$this->assertEqual(count($terms), 0, 'No terms loaded when restricted by a non-existing vocabulary.');
}
/**
* Tests that editing and saving a node with no changes works correctly.
*/
function testReSavingTags() {
// Enable tags in the vocabulary.
$field = $this->field;
entity_get_form_display($field->getTargetEntityTypeId(), $field->getTargetBundle(), 'default')
->setComponent($field->getName(), array(
'type' => 'entity_reference_autocomplete_tags',
))
->save();
// Create a term and a node using it.
$term = $this->createTerm($this->vocabulary);
$edit = array();
$edit['title[0][value]'] = $this->randomMachineName(8);
$edit['body[0][value]'] = $this->randomMachineName(16);
$edit[$this->field->getName() . '[target_id]'] = $term->getName();
$this->drupalPostForm('node/add/article', $edit, t('Save'));
// Check that the term is displayed when editing and saving the node with no
// changes.
$this->clickLink(t('Edit'));
$this->assertRaw($term->getName(), 'Term is displayed when editing the node.');
$this->drupalPostForm(NULL, array(), t('Save'));
$this->assertRaw($term->getName(), 'Term is displayed after saving the node with no changes.');
}
/**
* Check the breadcrumb on edit and delete a term page.
*/
public function testTermBreadcrumbs() {
$edit = [
'name[0][value]' => $this->randomMachineName(14),
'description[0][value]' => $this->randomMachineName(100),
'parent[]' => [0],
];
// Create the term.
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add', $edit, t('Save'));
$terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']);
$term = reset($terms);
$this->assertNotNull($term, 'Term found in database.');
// Check the breadcrumb on the term edit page.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$breadcrumbs = $this->cssSelect('nav.breadcrumb ol li a');
$this->assertIdentical(count($breadcrumbs), 2, 'The breadcrumbs are present on the page.');
$this->assertIdentical((string) $breadcrumbs[0], 'Home', 'First breadcrumb text is Home');
$this->assertIdentical((string) $breadcrumbs[1], $term->label(), 'Second breadcrumb text is term name on term edit page.');
$this->assertEscaped((string) $breadcrumbs[1], 'breadcrumbs displayed and escaped.');
// Check the breadcrumb on the term delete page.
$this->drupalGet('taxonomy/term/' . $term->id() . '/delete');
$breadcrumbs = $this->cssSelect('nav.breadcrumb ol li a');
$this->assertIdentical(count($breadcrumbs), 2, 'The breadcrumbs are present on the page.');
$this->assertIdentical((string) $breadcrumbs[0], 'Home', 'First breadcrumb text is Home');
$this->assertIdentical((string) $breadcrumbs[1], $term->label(), 'Second breadcrumb text is term name on term delete page.');
$this->assertEscaped((string) $breadcrumbs[1], 'breadcrumbs displayed and escaped.');
}
}

View file

@ -0,0 +1,105 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\node\Entity\Node;
/**
* Tests the translation of taxonomy terms field on nodes.
*
* @group taxonomy
*/
class TermTranslationFieldViewTest extends TaxonomyTestBase {
use TaxonomyTranslationTestTrait;
/**
* The term that should be translated.
*
* @var \Drupal\taxonomy\Entity\Term
*/
protected $term;
/**
* The tag in the source language.
*
* @var string
*/
protected $baseTagName = 'OriginalTagName';
/**
* The translated value for the tag.
*
* @var string
*/
protected $translatedTagName = 'TranslatedTagName';
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('language', 'content_translation', 'taxonomy');
protected function setUp() {
parent::setUp();
$this->setupLanguages();
$this->vocabulary = $this->createVocabulary();
$this->enableTranslation();
$this->setUpTerm();
$this->setUpTermReferenceField();
$this->setUpNode();
}
/**
* Tests if the translated taxonomy term is displayed.
*/
public function testTranslatedTaxonomyTermReferenceDisplay() {
$path = 'node/' . $this->node->id();
$translation_path = $this->translateToLangcode . '/' . $path;
$this->drupalGet($path);
$this->assertNoText($this->translatedTagName);
$this->assertText($this->baseTagName);
$this->drupalGet($translation_path);
$this->assertText($this->translatedTagName);
$this->assertNoText($this->baseTagName);
}
/**
* Creates a test subject node, with translation.
*/
protected function setUpNode() {
/** @var \Drupal\node\Entity\Node $node */
$node = Node::create([
'title' => $this->randomMachineName(),
'type' => 'article',
'description' => [[
'value' => $this->randomMachineName(),
'format' => 'basic_html'
]],
$this->termFieldName => array(array('target_id' => $this->term->id())),
'langcode' => $this->baseLangcode,
]);
$node->save();
$node->addTranslation($this->translateToLangcode, $node->toArray());
$node->save();
$this->node = $node;
}
/**
* Creates a test subject term, with translation.
*/
protected function setUpTerm() {
$this->term = $this->createTerm($this->vocabulary, array(
'name' => $this->baseTagName,
'langcode' => $this->baseLangcode,
));
$this->term->addTranslation($this->translateToLangcode, array(
'name' => $this->translatedTagName,
));
$this->term->save();
}
}

View file

@ -0,0 +1,149 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Core\Url;
use Drupal\system\Tests\Menu\AssertBreadcrumbTrait;
/**
* Tests for proper breadcrumb translation.
*
* @group taxonomy
*/
class TermTranslationTest extends TaxonomyTestBase {
use AssertBreadcrumbTrait;
use TaxonomyTranslationTestTrait;
/**
* Term to translated term mapping.
*
* @var array
*/
protected $termTranslationMap = array(
'one' => 'translatedOne',
'two' => 'translatedTwo',
'three' => 'translatedThree',
);
/**
* Created terms.
*
* @var \Drupal\taxonomy\Entity\Term[]
*/
protected $terms = array();
/**
* {@inheritdoc}
*/
public static $modules = array('taxonomy', 'language', 'content_translation');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->setupLanguages();
$this->vocabulary = $this->createVocabulary();
$this->enableTranslation();
$this->setUpTerms();
$this->setUpTermReferenceField();
}
/**
* Test translated breadcrumbs.
*/
public function testTranslatedBreadcrumbs() {
// Ensure non-translated breadcrumb is correct.
$breadcrumb = array(Url::fromRoute('<front>')->toString() => 'Home');
foreach ($this->terms as $term) {
$breadcrumb[$term->url()] = $term->label();
}
// The last item will not be in the breadcrumb.
array_pop($breadcrumb);
// Check the breadcrumb on the leaf term page.
$term = $this->getLeafTerm();
$this->assertBreadcrumb($term->urlInfo(), $breadcrumb, $term->label());
$languages = \Drupal::languageManager()->getLanguages();
// Construct the expected translated breadcrumb.
$breadcrumb = array(Url::fromRoute('<front>', [], ['language' => $languages[$this->translateToLangcode]])->toString() => 'Home');
foreach ($this->terms as $term) {
$translated = $term->getTranslation($this->translateToLangcode);
$url = $translated->url('canonical', ['language' => $languages[$this->translateToLangcode]]);
$breadcrumb[$url] = $translated->label();
}
array_pop($breadcrumb);
// Check for the translated breadcrumb on the translated leaf term page.
$term = $this->getLeafTerm();
$translated = $term->getTranslation($this->translateToLangcode);
$this->assertBreadcrumb($translated->urlInfo('canonical', ['language' => $languages[$this->translateToLangcode]]), $breadcrumb, $translated->label());
}
/**
* Test translation of terms are showed in the node.
*/
protected function testTermsTranslation() {
// Set the display of the term reference field on the article content type
// to "Check boxes/radio buttons".
entity_get_form_display('node', 'article', 'default')
->setComponent($this->termFieldName, array(
'type' => 'options_buttons',
))
->save();
$this->drupalLogin($this->drupalCreateUser(['create article content']));
// Test terms are listed.
$this->drupalget('node/add/article');
$this->assertText('one');
$this->assertText('two');
$this->assertText('three');
// Test terms translated are listed.
$this->drupalget('hu/node/add/article');
$this->assertText('translatedOne');
$this->assertText('translatedTwo');
$this->assertText('translatedThree');
}
/**
* Setup translated terms in a hierarchy.
*/
protected function setUpTerms() {
$parent_vid = 0;
foreach ($this->termTranslationMap as $name => $translation) {
$term = $this->createTerm($this->vocabulary, array(
'name' => $name,
'langcode' => $this->baseLangcode,
'parent' => $parent_vid,
));
$term->addTranslation($this->translateToLangcode, array(
'name' => $translation,
));
$term->save();
// Each term is nested under the last.
$parent_vid = $term->id();
$this->terms[] = $term;
}
}
/**
* Get the final (leaf) term in the hierarchy.
*
* @return \Drupal\taxonomy\Entity\Term
* The final term in the hierarchy.
*/
protected function getLeafTerm() {
return $this->terms[count($this->termTranslationMap) - 1];
}
}

View file

@ -0,0 +1,164 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\content_translation\Tests\ContentTranslationUITestBase;
use Drupal\Core\Language\LanguageInterface;
use Drupal\taxonomy\Entity\Vocabulary;
/**
* Tests the Term Translation UI.
*
* @group taxonomy
*/
class TermTranslationUITest extends ContentTranslationUITestBase {
/**
* The vocabulary used for creating terms.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('language', 'content_translation', 'taxonomy');
protected function setUp() {
$this->entityTypeId = 'taxonomy_term';
$this->bundle = 'tags';
parent::setUp();
}
/**
* {@inheritdoc}
*/
protected function setupBundle() {
parent::setupBundle();
// Create a vocabulary.
$this->vocabulary = Vocabulary::create([
'name' => $this->bundle,
'description' => $this->randomMachineName(),
'vid' => $this->bundle,
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
'weight' => mt_rand(0, 10),
]);
$this->vocabulary->save();
}
/**
* {@inheritdoc}
*/
protected function getTranslatorPermissions() {
return array_merge(parent::getTranslatorPermissions(), array('administer taxonomy'));
}
/**
* {@inheritdoc}
*/
protected function getNewEntityValues($langcode) {
return array('name' => $this->randomMachineName()) + parent::getNewEntityValues($langcode);
}
/**
* Returns an edit array containing the values to be posted.
*/
protected function getEditValues($values, $langcode, $new = FALSE) {
$edit = parent::getEditValues($values, $langcode, $new);
// To be able to post values for the configurable base fields (name,
// description) have to be suffixed with [0][value].
foreach ($edit as $property => $value) {
foreach (array('name', 'description') as $key) {
if ($property == $key) {
$edit[$key . '[0][value]'] = $value;
unset($edit[$property]);
}
}
}
return $edit;
}
/**
* {@inheritdoc}
*/
public function testTranslationUI() {
parent::testTranslationUI();
// Make sure that no row was inserted for taxonomy vocabularies which do
// not have translations enabled.
$rows = db_query('SELECT tid, count(tid) AS count FROM {taxonomy_term_field_data} WHERE vid <> :vid GROUP BY tid', array(':vid' => $this->bundle))->fetchAll();
foreach ($rows as $row) {
$this->assertTrue($row->count < 2, 'Term does not have translations.');
}
}
/**
* Tests translate link on vocabulary term list.
*/
function testTranslateLinkVocabularyAdminPage() {
$this->drupalLogin($this->drupalCreateUser(array_merge(parent::getTranslatorPermissions(), ['access administration pages', 'administer taxonomy'])));
$values = array(
'name' => $this->randomMachineName(),
);
$translatable_tid = $this->createEntity($values, $this->langcodes[0], $this->vocabulary->id());
// Create an untranslatable vocabulary.
$untranslatable_vocabulary = Vocabulary::create([
'name' => 'untranslatable_voc',
'description' => $this->randomMachineName(),
'vid' => 'untranslatable_voc',
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
'weight' => mt_rand(0, 10),
]);
$untranslatable_vocabulary->save();
$values = array(
'name' => $this->randomMachineName(),
);
$untranslatable_tid = $this->createEntity($values, $this->langcodes[0], $untranslatable_vocabulary->id());
// Verify translation links.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->assertResponse(200, 'The translatable vocabulary page was found.');
$this->assertLinkByHref('term/' . $translatable_tid . '/translations', 0, 'The translations link exists for a translatable vocabulary.');
$this->assertLinkByHref('term/' . $translatable_tid . '/edit', 0, 'The edit link exists for a translatable vocabulary.');
$this->drupalGet('admin/structure/taxonomy/manage/' . $untranslatable_vocabulary->id() . '/overview');
$this->assertResponse(200);
$this->assertLinkByHref('term/' . $untranslatable_tid . '/edit');
$this->assertNoLinkByHref('term/' . $untranslatable_tid . '/translations');
}
/**
* {@inheritdoc}
*/
protected function doTestTranslationEdit() {
$storage = $this->container->get('entity_type.manager')
->getStorage($this->entityTypeId);
$storage->resetCache([$this->entityId]);
$entity = $storage->load($this->entityId);
$languages = $this->container->get('language_manager')->getLanguages();
foreach ($this->langcodes as $langcode) {
// We only want to test the title for non-english translations.
if ($langcode != 'en') {
$options = array('language' => $languages[$langcode]);
$url = $entity->urlInfo('edit-form', $options);
$this->drupalGet($url);
$title = t('@title [%language translation]', array(
'@title' => $entity->getTranslation($langcode)->label(),
'%language' => $languages[$langcode]->getName(),
));
$this->assertRaw($title);
}
}
}
}

View file

@ -0,0 +1,49 @@
<?php
namespace Drupal\taxonomy\Tests;
/**
* Verifies that various taxonomy pages use the expected theme.
*
* @group taxonomy
*/
class ThemeTest extends TaxonomyTestBase {
protected function setUp() {
parent::setUp();
// Make sure we are using distinct default and administrative themes for
// the duration of these tests.
\Drupal::service('theme_handler')->install(array('bartik', 'seven'));
$this->config('system.theme')
->set('default', 'bartik')
->set('admin', 'seven')
->save();
// Create and log in as a user who has permission to add and edit taxonomy
// terms and view the administrative theme.
$admin_user = $this->drupalCreateUser(array('administer taxonomy', 'view the administration theme'));
$this->drupalLogin($admin_user);
}
/**
* Test the theme used when adding, viewing and editing taxonomy terms.
*/
function testTaxonomyTermThemes() {
// Adding a term to a vocabulary is considered an administrative action and
// should use the administrative theme.
$vocabulary = $this->createVocabulary();
$this->drupalGet('admin/structure/taxonomy/manage/' . $vocabulary->id() . '/add');
$this->assertRaw('seven/css/base/elements.css', t("The administrative theme's CSS appears on the page for adding a taxonomy term."));
// Viewing a taxonomy term should use the default theme.
$term = $this->createTerm($vocabulary);
$this->drupalGet('taxonomy/term/' . $term->id());
$this->assertRaw('bartik/css/base/elements.css', t("The default theme's CSS appears on the page for viewing a taxonomy term."));
// Editing a taxonomy term should use the same theme as adding one.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$this->assertRaw('seven/css/base/elements.css', t("The administrative theme's CSS appears on the page for editing a taxonomy term."));
}
}

View file

@ -0,0 +1,147 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Render\BubbleableMetadata;
/**
* Generates text using placeholders for dummy content to check taxonomy token
* replacement.
*
* @group taxonomy
*/
class TokenReplaceTest extends TaxonomyTestBase {
/**
* The vocabulary used for creating terms.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* Name of the taxonomy term reference field.
*
* @var string
*/
protected $fieldName;
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'bypass node access']));
$this->vocabulary = $this->createVocabulary();
$this->fieldName = 'taxonomy_' . $this->vocabulary->id();
$handler_settings = array(
'target_bundles' => array(
$this->vocabulary->id() => $this->vocabulary->id(),
),
'auto_create' => TRUE,
);
$this->createEntityReferenceField('node', 'article', $this->fieldName, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
entity_get_form_display('node', 'article', 'default')
->setComponent($this->fieldName, array(
'type' => 'options_select',
))
->save();
entity_get_display('node', 'article', 'default')
->setComponent($this->fieldName, array(
'type' => 'entity_reference_label',
))
->save();
}
/**
* Creates some terms and a node, then tests the tokens generated from them.
*/
function testTaxonomyTokenReplacement() {
$token_service = \Drupal::token();
$language_interface = \Drupal::languageManager()->getCurrentLanguage();
// Create two taxonomy terms.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
// Edit $term2, setting $term1 as parent.
$edit = array();
$edit['name[0][value]'] = '<blink>Blinking Text</blink>';
$edit['parent[]'] = array($term1->id());
$this->drupalPostForm('taxonomy/term/' . $term2->id() . '/edit', $edit, t('Save'));
// Create node with term2.
$edit = array();
$node = $this->drupalCreateNode(array('type' => 'article'));
$edit[$this->fieldName . '[]'] = $term2->id();
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
// Generate and test sanitized tokens for term1.
$tests = array();
$tests['[term:tid]'] = $term1->id();
$tests['[term:name]'] = $term1->getName();
$tests['[term:description]'] = $term1->description->processed;
$tests['[term:url]'] = $term1->url('canonical', array('absolute' => TRUE));
$tests['[term:node-count]'] = 0;
$tests['[term:parent:name]'] = '[term:parent:name]';
$tests['[term:vocabulary:name]'] = $this->vocabulary->label();
$tests['[term:vocabulary]'] = $this->vocabulary->label();
$base_bubbleable_metadata = BubbleableMetadata::createFromObject($term1);
$metadata_tests = array();
$metadata_tests['[term:tid]'] = $base_bubbleable_metadata;
$metadata_tests['[term:name]'] = $base_bubbleable_metadata;
$metadata_tests['[term:description]'] = $base_bubbleable_metadata;
$metadata_tests['[term:url]'] = $base_bubbleable_metadata;
$metadata_tests['[term:node-count]'] = $base_bubbleable_metadata;
$metadata_tests['[term:parent:name]'] = $base_bubbleable_metadata;
$bubbleable_metadata = clone $base_bubbleable_metadata;
$metadata_tests['[term:vocabulary:name]'] = $bubbleable_metadata->addCacheTags($this->vocabulary->getCacheTags());
$metadata_tests['[term:vocabulary]'] = $bubbleable_metadata->addCacheTags($this->vocabulary->getCacheTags());
foreach ($tests as $input => $expected) {
$bubbleable_metadata = new BubbleableMetadata();
$output = $token_service->replace($input, array('term' => $term1), array('langcode' => $language_interface->getId()), $bubbleable_metadata);
$this->assertEqual($output, $expected, format_string('Sanitized taxonomy term token %token replaced.', array('%token' => $input)));
$this->assertEqual($bubbleable_metadata, $metadata_tests[$input]);
}
// Generate and test sanitized tokens for term2.
$tests = array();
$tests['[term:tid]'] = $term2->id();
$tests['[term:name]'] = $term2->getName();
$tests['[term:description]'] = $term2->description->processed;
$tests['[term:url]'] = $term2->url('canonical', array('absolute' => TRUE));
$tests['[term:node-count]'] = 1;
$tests['[term:parent:name]'] = $term1->getName();
$tests['[term:parent:url]'] = $term1->url('canonical', array('absolute' => TRUE));
$tests['[term:parent:parent:name]'] = '[term:parent:parent:name]';
$tests['[term:vocabulary:name]'] = $this->vocabulary->label();
// Test to make sure that we generated something for each token.
$this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
foreach ($tests as $input => $expected) {
$output = $token_service->replace($input, array('term' => $term2), array('langcode' => $language_interface->getId()));
$this->assertEqual($output, $expected, format_string('Sanitized taxonomy term token %token replaced.', array('%token' => $input)));
}
// Generate and test sanitized tokens.
$tests = array();
$tests['[vocabulary:vid]'] = $this->vocabulary->id();
$tests['[vocabulary:name]'] = $this->vocabulary->label();
$tests['[vocabulary:description]'] = $this->vocabulary->getDescription();
$tests['[vocabulary:node-count]'] = 1;
$tests['[vocabulary:term-count]'] = 2;
// Test to make sure that we generated something for each token.
$this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
foreach ($tests as $input => $expected) {
$output = $token_service->replace($input, array('vocabulary' => $this->vocabulary), array('langcode' => $language_interface->getId()));
$this->assertEqual($output, $expected, format_string('Sanitized taxonomy vocabulary token %token replaced.', array('%token' => $input)));
}
}
}

View file

@ -0,0 +1,122 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\views\Views;
/**
* Tests the plugin of the taxonomy: term argument validator.
*
* @group taxonomy
* @see Views\taxonomy\Plugin\views\argument_validator\Term
*/
class ArgumentValidatorTermTest extends TaxonomyTestBase {
/**
* Stores the taxonomy term used by this test.
*
* @var array
*/
protected $terms = [];
/**
* Stores the taxonomy names used by this test.
*
* @var array
*/
protected $names = [];
/**
* Stores the taxonomy IDs used by this test.
*
* @var array
*/
protected $ids = [];
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['taxonomy', 'taxonomy_test_views', 'views_test_config'];
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_argument_validator_term'];
protected function setUp() {
parent::setUp();
// Add three terms to the 'tags' vocabulary.
for ($i = 0; $i < 3; $i++) {
$this->terms[] = $term = $this->createTerm();
$this->names[] = $term->label();
$this->ids[] = $term->id();
}
}
/**
* Tests the term argument validator plugin.
*/
public function testArgumentValidatorTerm() {
$view = Views::getView('test_argument_validator_term');
$view->initHandlers();
// Test the single validator for term IDs.
$view->argument['tid']->validator->options['type'] = 'tid';
// Pass in a single valid term.
foreach ($this->terms as $term) {
$this->assertTrue($view->argument['tid']->setArgument($term->id()));
$this->assertEqual($view->argument['tid']->getTitle(), $term->label());
$view->argument['tid']->validated_title = NULL;
$view->argument['tid']->argument_validated = NULL;
}
// Pass in a invalid term.
$this->assertFalse($view->argument['tid']->setArgument(rand(1000, 10000)));
$this->assertEqual('', $view->argument['tid']->getTitle());
$view->argument['tid']->validated_title = NULL;
$view->argument['tid']->argument_validated = NULL;
// Test the multiple validator for term IDs.
$view->argument['tid']->validator->options['type'] = 'tids';
$view->argument['tid']->options['break_phrase'] = TRUE;
// Pass in a single term.
$this->assertTrue($view->argument['tid']->setArgument($this->terms[0]->id()));
$this->assertEqual($view->argument['tid']->getTitle(), $this->terms[0]->label());
$view->argument['tid']->validated_title = NULL;
$view->argument['tid']->argument_validated = NULL;
// Check for multiple valid terms separated by commas.
$this->assertTrue($view->argument['tid']->setArgument(implode(',', $this->ids)));
$this->assertEqual($view->argument['tid']->getTitle(), implode(', ', $this->names));
$view->argument['tid']->validated_title = NULL;
$view->argument['tid']->argument_validated = NULL;
// Check for multiple valid terms separated by plus signs.
$this->assertTrue($view->argument['tid']->setArgument(implode('+', $this->ids)));
$this->assertEqual($view->argument['tid']->getTitle(), implode(' + ', $this->names));
$view->argument['tid']->validated_title = NULL;
$view->argument['tid']->argument_validated = NULL;
// Check for a single invalid term.
$this->assertFalse($view->argument['tid']->setArgument(rand(1000, 10000)));
$this->assertEqual('', $view->argument['tid']->getTitle());
$view->argument['tid']->validated_title = NULL;
$view->argument['tid']->argument_validated = NULL;
// Check for multiple invalid terms.
$this->assertFalse($view->argument['tid']->setArgument(implode(',', [rand(1000, 10000), rand(1000, 10000)])));
$this->assertEqual('', $view->argument['tid']->getTitle());
$view->argument['tid']->validated_title = NULL;
$view->argument['tid']->argument_validated = NULL;
}
}

View file

@ -0,0 +1,58 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\views\Views;
/**
* Tests the taxonomy term on node relationship handler.
*
* @group taxonomy
*/
class RelationshipNodeTermDataTest extends TaxonomyTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_taxonomy_node_term_data');
function testViewsHandlerRelationshipNodeTermData() {
$view = Views::getView('test_taxonomy_node_term_data');
// Tests \Drupal\taxonomy\Plugin\views\relationship\NodeTermData::calculateDependencies().
$expected = [
'config' => ['core.entity_view_mode.node.teaser'],
'module' => [
'node',
'taxonomy',
'user',
],
];
$this->assertIdentical($expected, $view->getDependencies());
$this->executeView($view, array($this->term1->id(), $this->term2->id()));
$expected_result = array(
array(
'nid' => $this->nodes[1]->id(),
),
array(
'nid' => $this->nodes[0]->id(),
),
);
$column_map = array('nid' => 'nid');
$this->assertIdenticalResultset($view, $expected_result, $column_map);
// Change the view to test relation limited by vocabulary.
$this->config('views.view.test_taxonomy_node_term_data')
->set('display.default.display_options.relationships.term_node_tid.vids', ['views_testing_tags'])
->save();
$view = Views::getView('test_taxonomy_node_term_data');
// Tests \Drupal\taxonomy\Plugin\views\relationship\NodeTermData::calculateDependencies().
$expected['config'][] = 'taxonomy.vocabulary.views_testing_tags';
$this->assertIdentical($expected, $view->getDependencies());
$this->executeView($view, array($this->term1->id(), $this->term2->id()));
$this->assertIdenticalResultset($view, $expected_result, $column_map);
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\views\Views;
/**
* Tests the representative node relationship for terms.
*
* @group taxonomy
*/
class RelationshipRepresentativeNodeTest extends TaxonomyTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_groupwise_term');
/**
* Tests the relationship.
*/
public function testRelationship() {
$view = Views::getView('test_groupwise_term');
$this->executeView($view);
$map = array('node_field_data_taxonomy_term_field_data_nid' => 'nid', 'tid' => 'tid');
$expected_result = array(
array(
'nid' => $this->nodes[1]->id(),
'tid' => $this->term2->id(),
),
array(
'nid' => $this->nodes[1]->id(),
'tid' => $this->term1->id(),
),
);
$this->assertIdenticalResultset($view, $expected_result, $map);
}
}

View file

@ -0,0 +1,100 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\field\Entity\FieldConfig;
use Drupal\views\Views;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Tests the representative node relationship for terms.
*
* @group taxonomy
*/
class TaxonomyDefaultArgumentTest extends TaxonomyTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('taxonomy_default_argument_test');
/**
* Tests the relationship.
*/
public function testNodePath() {
$view = Views::getView('taxonomy_default_argument_test');
$request = Request::create($this->nodes[0]->url());
$request->server->set('SCRIPT_NAME', $GLOBALS['base_path'] . 'index.php');
$request->server->set('SCRIPT_FILENAME', 'index.php');
$response = $this->container->get('http_kernel')
->handle($request, HttpKernelInterface::SUB_REQUEST);
$view->setRequest($request);
$view->setResponse($response);
$view->initHandlers();
$expected = implode(',', array($this->term1->id(), $this->term2->id()));
$this->assertEqual($expected, $view->argument['tid']->getDefaultArgument());
$view->destroy();
}
public function testNodePathWithViewSelection() {
// Change the term entity reference field to use a view as selection plugin.
\Drupal::service('module_installer')->install(['entity_reference_test']);
$field_name = 'field_' . $this->vocabulary->id();
$field = FieldConfig::loadByName('node', 'article', $field_name);
$field->setSetting('handler', 'views');
$field->setSetting('handler_settings', [
'view' => [
'view_name' => 'test_entity_reference',
'display_name' => 'entity_reference_1',
],
]);
$field->save();
$view = Views::getView('taxonomy_default_argument_test');
$request = Request::create($this->nodes[0]->url());
$request->server->set('SCRIPT_NAME', $GLOBALS['base_path'] . 'index.php');
$request->server->set('SCRIPT_FILENAME', 'index.php');
$response = $this->container->get('http_kernel')->handle($request, HttpKernelInterface::SUB_REQUEST);
$view->setRequest($request);
$view->setResponse($response);
$view->initHandlers();
$expected = implode(',', array($this->term1->id(), $this->term2->id()));
$this->assertEqual($expected, $view->argument['tid']->getDefaultArgument());
}
public function testTermPath() {
$view = Views::getView('taxonomy_default_argument_test');
$request = Request::create($this->term1->url());
$request->server->set('SCRIPT_NAME', $GLOBALS['base_path'] . 'index.php');
$request->server->set('SCRIPT_FILENAME', 'index.php');
$response = $this->container->get('http_kernel')->handle($request, HttpKernelInterface::SUB_REQUEST);
$view->setRequest($request);
$view->setResponse($response);
$view->initHandlers();
$expected = $this->term1->id();
$this->assertEqual($expected, $view->argument['tid']->getDefaultArgument());
}
/**
* Tests escaping of page title when the taxonomy plugin provides it.
*/
public function testTermTitleEscaping() {
$this->term1->setName('<em>Markup</em>')->save();
$this->drupalGet('taxonomy_default_argument_test/' . $this->term1->id());
$this->assertEscaped($this->term1->label());
}
}

View file

@ -0,0 +1,67 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\views\Views;
use Drupal\taxonomy\Entity\Vocabulary;
/**
* Tests the "All terms" taxonomy term field handler.
*
* @group taxonomy
*/
class TaxonomyFieldAllTermsTest extends TaxonomyTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('taxonomy_all_terms_test');
/**
* Tests the "all terms" field handler.
*/
public function testViewsHandlerAllTermsField() {
$this->term1->setName('<em>Markup</em>')->save();
$view = Views::getView('taxonomy_all_terms_test');
$this->executeView($view);
$this->drupalGet('taxonomy_all_terms_test');
$actual = $this->xpath('//a[@href="' . $this->term1->url() . '"]');
$this->assertEqual(count($actual), 2, 'Correct number of taxonomy term1 links');
$this->assertEqual($actual[0]->__toString(), $this->term1->label());
$this->assertEqual($actual[1]->__toString(), $this->term1->label());
$this->assertEscaped($this->term1->label());
$actual = $this->xpath('//a[@href="' . $this->term2->url() . '"]');
$this->assertEqual(count($actual), 2, 'Correct number of taxonomy term2 links');
$this->assertEqual($actual[0]->__toString(), $this->term2->label());
$this->assertEqual($actual[1]->__toString(), $this->term2->label());
}
/**
* Tests token replacement in the "all terms" field handler.
*/
public function testViewsHandlerAllTermsWithTokens() {
$view = Views::getView('taxonomy_all_terms_test');
$this->drupalGet('taxonomy_all_terms_token_test');
// Term itself: {{ term_node_tid }}
$this->assertText('Term: ' . $this->term1->getName());
// The taxonomy term ID for the term: {{ term_node_tid__tid }}
$this->assertText('The taxonomy term ID for the term: ' . $this->term1->id());
// The taxonomy term name for the term: {{ term_node_tid__name }}
$this->assertText('The taxonomy term name for the term: ' . $this->term1->getName());
// The machine name for the vocabulary the term belongs to: {{ term_node_tid__vocabulary_vid }}
$this->assertText('The machine name for the vocabulary the term belongs to: ' . $this->term1->getVocabularyId());
// The name for the vocabulary the term belongs to: {{ term_node_tid__vocabulary }}
$vocabulary = Vocabulary::load($this->term1->bundle());
$this->assertText('The name for the vocabulary the term belongs to: ' . $vocabulary->label());
}
}

View file

@ -0,0 +1,185 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\Core\Language\LanguageInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\views\Tests\ViewTestBase;
use Drupal\views\Tests\ViewTestData;
use Drupal\views\Views;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\Entity\Term;
/**
* Tests taxonomy field filters with translations.
*
* @group taxonomy
*/
class TaxonomyFieldFilterTest extends ViewTestBase {
/**
* {@inheritdoc}
*/
public static $modules = array('language', 'taxonomy', 'taxonomy_test_views', 'text', 'views', 'node');
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_field_filters');
/**
* The vocabulary used for creating terms.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* List of taxonomy term names by language.
*
* @var array
*/
public $termNames = [];
function setUp() {
parent::setUp();
// Add two new languages.
ConfigurableLanguage::createFromLangcode('fr')->save();
ConfigurableLanguage::createFromLangcode('es')->save();
// Set up term names.
$this->termNames = array(
'en' => 'Food in Paris',
'es' => 'Comida en Paris',
'fr' => 'Nouriture en Paris',
);
// Create a vocabulary.
$this->vocabulary = Vocabulary::create([
'name' => 'Views testing tags',
'vid' => 'views_testing_tags',
]);
$this->vocabulary->save();
// Add a translatable field to the vocabulary.
$field = FieldStorageConfig::create(array(
'field_name' => 'field_foo',
'entity_type' => 'taxonomy_term',
'type' => 'text',
));
$field->save();
FieldConfig::create([
'field_name' => 'field_foo',
'entity_type' => 'taxonomy_term',
'label' => 'Foo',
'bundle' => 'views_testing_tags',
])->save();
// Create term with translations.
$taxonomy = $this->createTermWithProperties(array('name' => $this->termNames['en'], 'langcode' => 'en', 'description' => $this->termNames['en'], 'field_foo' => $this->termNames['en']));
foreach (array('es', 'fr') as $langcode) {
$translation = $taxonomy->addTranslation($langcode, array('name' => $this->termNames[$langcode]));
$translation->description->value = $this->termNames[$langcode];
$translation->field_foo->value = $this->termNames[$langcode];
}
$taxonomy->save();
Views::viewsData()->clear();
ViewTestData::createTestViews(get_class($this), array('taxonomy_test_views'));
$this->container->get('router.builder')->rebuild();
}
/**
* Tests description and term name filters.
*/
public function testFilters() {
// Test the name filter page, which filters for name contains 'Comida'.
// Should show just the Spanish translation, once.
$this->assertPageCounts('test-name-filter', array('es' => 1, 'fr' => 0, 'en' => 0), 'Comida name filter');
// Test the description filter page, which filters for description contains
// 'Comida'. Should show just the Spanish translation, once.
$this->assertPageCounts('test-desc-filter', array('es' => 1, 'fr' => 0, 'en' => 0), 'Comida description filter');
// Test the field filter page, which filters for field_foo contains
// 'Comida'. Should show just the Spanish translation, once.
$this->assertPageCounts('test-field-filter', array('es' => 1, 'fr' => 0, 'en' => 0), 'Comida field filter');
// Test the name Paris filter page, which filters for name contains
// 'Paris'. Should show each translation once.
$this->assertPageCounts('test-name-paris', array('es' => 1, 'fr' => 1, 'en' => 1), 'Paris name filter');
// Test the description Paris page, which filters for description contains
// 'Paris'. Should show each translation, once.
$this->assertPageCounts('test-desc-paris', array('es' => 1, 'fr' => 1, 'en' => 1), 'Paris description filter');
// Test the field Paris filter page, which filters for field_foo contains
// 'Paris'. Should show each translation once.
$this->assertPageCounts('test-field-paris', array('es' => 1, 'fr' => 1, 'en' => 1), 'Paris field filter');
}
/**
* Asserts that the given taxonomy translation counts are correct.
*
* @param string $path
* Path of the page to test.
* @param array $counts
* Array whose keys are languages, and values are the number of times
* that translation should be shown on the given page.
* @param string $message
* Message suffix to display.
*/
protected function assertPageCounts($path, $counts, $message) {
// Get the text of the page.
$this->drupalGet($path);
$text = $this->getTextContent();
// Check the counts. Note that the title and body are both shown on the
// page, and they are the same. So the title/body string should appear on
// the page twice as many times as the input count.
foreach ($counts as $langcode => $count) {
$this->assertEqual(substr_count($text, $this->termNames[$langcode]), 2 * $count, 'Translation ' . $langcode . ' has count ' . $count . ' with ' . $message);
}
}
/**
* Creates a taxonomy term with specified name and other properties.
*
* @param array $properties
* Array of properties and field values to set.
*
* @return \Drupal\taxonomy\TermInterface
* The created taxonomy term.
*/
protected function createTermWithProperties($properties) {
// Use the first available text format.
$filter_formats = filter_formats();
$format = array_pop($filter_formats);
$properties += array(
'name' => $this->randomMachineName(),
'description' => $this->randomMachineName(),
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
'field_foo' => $this->randomMachineName(),
);
$term = Term::create([
'name' => $properties['name'],
'description' => $properties['description'],
'format' => $format->id(),
'vid' => $this->vocabulary->id(),
'langcode' => $properties['langcode'],
]);
$term->field_foo->value = $properties['field_foo'];
$term->save();
return $term;
}
}

View file

@ -0,0 +1,37 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\Core\Render\RenderContext;
use Drupal\views\Views;
/**
* Tests the taxonomy term TID field handler.
*
* @group taxonomy
*/
class TaxonomyFieldTidTest extends TaxonomyTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_taxonomy_tid_field');
function testViewsHandlerTidField() {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = \Drupal::service('renderer');
$view = Views::getView('test_taxonomy_tid_field');
$this->executeView($view);
$actual = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$expected = \Drupal::l($this->term1->label(), $this->term1->urlInfo());
$this->assertEqual($expected, $actual);
}
}

View file

@ -0,0 +1,156 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\views\Entity\View;
use Drupal\views\Tests\ViewTestData;
/**
* Test the taxonomy term index filter.
*
* @see \Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid
*
* @group taxonomy
*/
class TaxonomyIndexTidFilterTest extends TaxonomyTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['taxonomy', 'taxonomy_test_views', 'views', 'node'];
/**
* {@inheritdoc}
*/
public static $testViews = ['test_filter_taxonomy_index_tid__non_existing_dependency'];
/**
* @var \Drupal\taxonomy\TermInterface[]
*/
protected $terms = [];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp(FALSE);
// Setup vocabulary and terms so the initial import is valid.
Vocabulary::create([
'vid' => 'tags',
'name' => 'Tags',
])->save();
// This will get a term ID of 3.
$term = Term::create([
'vid' => 'tags',
'name' => 'muh',
]);
$term->save();
// This will get a term ID of 4.
$this->terms[$term->id()] = $term;
$term = Term::create([
'vid' => 'tags',
'name' => 'muh',
]);
$term->save();
$this->terms[$term->id()] = $term;
ViewTestData::createTestViews(get_class($this), array('taxonomy_test_views'));
}
/**
* Tests dependencies are not added for terms that do not exist.
*/
public function testConfigDependency() {
/** @var \Drupal\views\Entity\View $view */
$view = View::load('test_filter_taxonomy_index_tid__non_existing_dependency');
// Dependencies are sorted.
$content_dependencies = [
$this->terms[3]->getConfigDependencyName(),
$this->terms[4]->getConfigDependencyName(),
];
sort($content_dependencies);
$this->assertEqual([
'config' => [
'taxonomy.vocabulary.tags',
],
'content' => $content_dependencies,
'module' => [
'node',
'taxonomy',
'user',
],
], $view->calculateDependencies()->getDependencies());
$this->terms[3]->delete();
$this->assertEqual([
'config' => [
'taxonomy.vocabulary.tags',
],
'content' => [
$this->terms[4]->getConfigDependencyName(),
],
'module' => [
'node',
'taxonomy',
'user',
],
], $view->calculateDependencies()->getDependencies());
}
/**
* Tests post update function fixes dependencies.
*
* @see views_post_update_taxonomy_index_tid()
*/
public function testPostUpdateFunction() {
/** @var \Drupal\views\Entity\View $view */
$view = View::load('test_filter_taxonomy_index_tid__non_existing_dependency');
// Dependencies are sorted.
$content_dependencies = [
$this->terms[3]->getConfigDependencyName(),
$this->terms[4]->getConfigDependencyName(),
];
sort($content_dependencies);
$this->assertEqual([
'config' => [
'taxonomy.vocabulary.tags',
],
'content' => $content_dependencies,
'module' => [
'node',
'taxonomy',
'user',
],
], $view->calculateDependencies()->getDependencies());
$this->terms[3]->delete();
\Drupal::moduleHandler()->loadInclude('views', 'post_update.php');
views_post_update_taxonomy_index_tid();
$view = View::load('test_filter_taxonomy_index_tid__non_existing_dependency');
$this->assertEqual([
'config' => [
'taxonomy.vocabulary.tags',
],
'content' => [
$this->terms[4]->getConfigDependencyName(),
],
'module' => [
'node',
'taxonomy',
'user',
],
], $view->getDependencies());
}
}

View file

@ -0,0 +1,221 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\views\Tests\ViewTestData;
use Drupal\views_ui\Tests\UITestBase;
use Drupal\views\Entity\View;
/**
* Tests the taxonomy index filter handler UI.
*
* @group taxonomy
* @see \Drupal\taxonomy\Plugin\views\field\TaxonomyIndexTid
*/
class TaxonomyIndexTidUiTest extends UITestBase {
use EntityReferenceTestTrait;
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_filter_taxonomy_index_tid', 'test_taxonomy_term_name');
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['node', 'taxonomy', 'views', 'views_ui', 'taxonomy_test_views'];
/**
* A nested array of \Drupal\taxonomy\TermInterface objects.
*
* @var \Drupal\taxonomy\TermInterface[][]
*/
protected $terms = [];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->adminUser = $this->drupalCreateUser(['administer taxonomy', 'administer views']);
$this->drupalLogin($this->adminUser);
Vocabulary::create([
'vid' => 'tags',
'name' => 'Tags',
])->save();
// Setup a hierarchy which looks like this:
// term 0.0
// term 1.0
// - term 1.1
// term 2.0
// - term 2.1
// - term 2.2
for ($i = 0; $i < 3; $i++) {
for ($j = 0; $j <= $i; $j++) {
$this->terms[$i][$j] = $term = Term::create([
'vid' => 'tags',
'name' => "Term $i.$j",
'parent' => isset($terms[$i][0]) ? $terms[$i][0]->id() : 0,
]);
$term->save();
}
}
ViewTestData::createTestViews(get_class($this), array('taxonomy_test_views'));
Vocabulary::create([
'vid' => 'empty_vocabulary',
'name' => 'Empty Vocabulary',
])->save();
}
/**
* Tests the filter UI.
*/
public function testFilterUI() {
$this->drupalGet('admin/structure/views/nojs/handler/test_filter_taxonomy_index_tid/default/filter/tid');
$result = $this->xpath('//select[@id="edit-options-value"]/option');
// Ensure that the expected hierarchy is available in the UI.
$counter = 0;
for ($i = 0; $i < 3; $i++) {
for ($j = 0; $j <= $i; $j++) {
$option = $result[$counter++];
$prefix = $this->terms[$i][$j]->parent->target_id ? '-' : '';
$attributes = $option->attributes();
$tid = (string) $attributes->value;
$this->assertEqual($prefix . $this->terms[$i][$j]->getName(), (string) $option);
$this->assertEqual($this->terms[$i][$j]->id(), $tid);
}
}
// Ensure the autocomplete input element appears when using the 'textfield'
// type.
$view = View::load('test_filter_taxonomy_index_tid');
$display =& $view->getDisplay('default');
$display['display_options']['filters']['tid']['type'] = 'textfield';
$view->save();
$this->drupalGet('admin/structure/views/nojs/handler/test_filter_taxonomy_index_tid/default/filter/tid');
$this->assertFieldByXPath('//input[@id="edit-options-value"]');
// Tests \Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid::calculateDependencies().
$expected = [
'config' => [
'taxonomy.vocabulary.tags',
],
'content' => [
'taxonomy_term:tags:' . Term::load(2)->uuid(),
],
'module' => [
'node',
'taxonomy',
'user',
],
];
$this->assertIdentical($expected, $view->calculateDependencies()->getDependencies());
}
/**
* Tests exposed taxonomy filters.
*/
public function testExposedFilter() {
$node_type = $this->drupalCreateContentType(['type' => 'page']);
// Create the tag field itself.
$field_name = 'taxonomy_tags';
$this->createEntityReferenceField('node', $node_type->id(), $field_name, NULL, 'taxonomy_term');
// Create 4 nodes: 1 without a term, 2 with the same term, and 1 with a
// different term.
$node1 = $this->drupalCreateNode();
$node2 = $this->drupalCreateNode([
$field_name => [['target_id' => $this->terms[1][0]->id()]],
]);
$node3 = $this->drupalCreateNode([
$field_name => [['target_id' => $this->terms[1][0]->id()]],
]);
$node4 = $this->drupalCreateNode([
$field_name => [['target_id' => $this->terms[2][0]->id()]],
]);
// Only the nodes with the selected term should be shown.
$this->drupalGet('test-filter-taxonomy-index-tid');
$xpath = $this->xpath('//div[@class="view-content"]//a');
$this->assertIdentical(2, count($xpath));
$xpath = $this->xpath('//div[@class="view-content"]//a[@href=:href]', [':href' => $node2->url()]);
$this->assertIdentical(1, count($xpath));
$xpath = $this->xpath('//div[@class="view-content"]//a[@href=:href]', [':href' => $node3->url()]);
$this->assertIdentical(1, count($xpath));
// Expose the filter.
$this->drupalPostForm('admin/structure/views/nojs/handler/test_filter_taxonomy_index_tid/default/filter/tid', [], 'Expose filter');
// Set the operator to 'empty' and remove the default term ID.
$this->drupalPostForm(NULL, [
'options[operator]' => 'empty',
'options[value][]' => [],
], 'Apply');
// Save the view.
$this->drupalPostForm(NULL, [], 'Save');
// After switching to 'empty' operator, the node without a term should be
// shown.
$this->drupalGet('test-filter-taxonomy-index-tid');
$xpath = $this->xpath('//div[@class="view-content"]//a');
$this->assertIdentical(1, count($xpath));
$xpath = $this->xpath('//div[@class="view-content"]//a[@href=:href]', [':href' => $node1->url()]);
$this->assertIdentical(1, count($xpath));
// Set the operator to 'not empty'.
$this->drupalPostForm('admin/structure/views/nojs/handler/test_filter_taxonomy_index_tid/default/filter/tid', ['options[operator]' => 'not empty'], 'Apply');
// Save the view.
$this->drupalPostForm(NULL, [], 'Save');
// After switching to 'not empty' operator, all nodes with terms should be
// shown.
$this->drupalGet('test-filter-taxonomy-index-tid');
$xpath = $this->xpath('//div[@class="view-content"]//a');
$this->assertIdentical(3, count($xpath));
$xpath = $this->xpath('//div[@class="view-content"]//a[@href=:href]', [':href' => $node2->url()]);
$this->assertIdentical(1, count($xpath));
$xpath = $this->xpath('//div[@class="view-content"]//a[@href=:href]', [':href' => $node3->url()]);
$this->assertIdentical(1, count($xpath));
$xpath = $this->xpath('//div[@class="view-content"]//a[@href=:href]', [':href' => $node4->url()]);
$this->assertIdentical(1, count($xpath));
// Select 'Term ID' as the field to be displayed.
$edit = ['name[taxonomy_term_field_data.tid]' => TRUE];
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_taxonomy_term_name/default/field', $edit, 'Add and configure fields');
// Select 'Term' and 'Vocabulary' as filters.
$edit = [
'name[taxonomy_term_field_data.tid]' => TRUE,
'name[taxonomy_term_field_data.vid]' => TRUE
];
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_taxonomy_term_name/default/filter', $edit, 'Add and configure filter criteria');
// Select 'Empty Vocabulary' and 'Autocomplete' from the list of options.
$this->drupalPostForm('admin/structure/views/nojs/handler-extra/test_taxonomy_term_name/default/filter/tid', [], 'Apply and continue');
// Expose the filter.
$edit = ['options[expose_button][checkbox][checkbox]' => TRUE];
$this->drupalPostForm('admin/structure/views/nojs/handler/test_taxonomy_term_name/default/filter/tid', $edit, 'Expose filter');
$this->drupalPostForm('admin/structure/views/nojs/handler/test_taxonomy_term_name/default/filter/tid', $edit, 'Apply');
// Filter 'Taxonomy terms' belonging to 'Empty Vocabulary'.
$edit = ['options[value][empty_vocabulary]' => TRUE];
$this->drupalPostForm('admin/structure/views/nojs/handler/test_taxonomy_term_name/default/filter/vid', $edit, 'Apply');
$this->drupalPostForm('admin/structure/views/view/test_taxonomy_term_name/edit/default', [], 'Save');
$this->drupalPostForm(NULL, [], t('Update preview'));
$preview = $this->xpath("//div[@class='view-content']");
$this->assertTrue(empty($preview), 'No results.');
}
}

View file

@ -0,0 +1,47 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\views\Tests\ViewTestData;
use Drupal\views_ui\Tests\UITestBase;
/**
* Tests views taxonomy parent plugin UI.
*
* @group taxonomy
* @see Drupal\taxonomy\Plugin\views\access\Role
*/
class TaxonomyParentUITest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_taxonomy_parent');
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('taxonomy', 'taxonomy_test_views');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
ViewTestData::createTestViews(get_class($this), array('taxonomy_test_views'));
}
/**
* Tests the taxonomy parent plugin UI.
*/
public function testTaxonomyParentUI() {
$this->drupalGet('admin/structure/views/nojs/handler/test_taxonomy_parent/default/relationship/parent');
$this->assertNoText('The handler for this item is broken or missing.');
}
}

View file

@ -0,0 +1,105 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\node\NodeInterface;
use Drupal\taxonomy\TermInterface;
use Drupal\views\Views;
/**
* Tests taxonomy relationships with parent term and node.
*
* @group taxonomy
*/
class TaxonomyRelationshipTest extends TaxonomyTestBase {
/**
* Stores the terms used in the tests.
*
* @var \Drupal\taxonomy\TermInterface[]
*/
protected $terms = array();
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_taxonomy_term_relationship');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Make term2 parent of term1.
$this->term1->set('parent', $this->term2->id());
$this->term1->save();
// Store terms in an array for testing.
$this->terms[] = $this->term1;
$this->terms[] = $this->term2;
// Only set term1 on node1 and term2 on node2 for testing.
unset($this->nodes[0]->field_views_testing_tags[1]);
$this->nodes[0]->save();
unset($this->nodes[1]->field_views_testing_tags[0]);
$this->nodes[1]->save();
Views::viewsData()->clear();
}
/**
* Tests the taxonomy parent plugin UI.
*/
public function testTaxonomyRelationships() {
// Check the generated views data of taxonomy_index.
$views_data = Views::viewsData()->get('taxonomy_index');
// Check the table join data.
$this->assertEqual($views_data['table']['join']['taxonomy_term_field_data']['left_field'], 'tid');
$this->assertEqual($views_data['table']['join']['taxonomy_term_field_data']['field'], 'tid');
$this->assertEqual($views_data['table']['join']['node_field_data']['left_field'], 'nid');
$this->assertEqual($views_data['table']['join']['node_field_data']['field'], 'nid');
$this->assertEqual($views_data['table']['join']['taxonomy_term_hierarchy']['left_field'], 'tid');
$this->assertEqual($views_data['table']['join']['taxonomy_term_hierarchy']['field'], 'tid');
// Check the generated views data of taxonomy_term_hierarchy.
$views_data = Views::viewsData()->get('taxonomy_term_hierarchy');
// Check the table join data.
$this->assertEqual($views_data['table']['join']['taxonomy_term_hierarchy']['left_field'], 'tid');
$this->assertEqual($views_data['table']['join']['taxonomy_term_hierarchy']['field'], 'parent');
$this->assertEqual($views_data['table']['join']['taxonomy_term_field_data']['left_field'], 'tid');
$this->assertEqual($views_data['table']['join']['taxonomy_term_field_data']['field'], 'tid');
// Check the parent relationship data.
$this->assertEqual($views_data['parent']['relationship']['base'], 'taxonomy_term_field_data');
$this->assertEqual($views_data['parent']['relationship']['field'], 'parent');
$this->assertEqual($views_data['parent']['relationship']['label'], t('Parent'));
$this->assertEqual($views_data['parent']['relationship']['id'], 'standard');
// Check the parent filter and argument data.
$this->assertEqual($views_data['parent']['filter']['id'], 'numeric');
$this->assertEqual($views_data['parent']['argument']['id'], 'taxonomy');
// Check an actual test view.
$view = Views::getView('test_taxonomy_term_relationship');
$this->executeView($view);
/** @var \Drupal\views\ResultRow $row */
foreach ($view->result as $index => $row) {
// Check that the actual ID of the entity is the expected one.
$this->assertEqual($row->tid, $this->terms[$index]->id());
// Also check that we have the correct result entity.
$this->assertEqual($row->_entity->id(), $this->terms[$index]->id());
$this->assertTrue($row->_entity instanceof TermInterface);
if (!$index) {
$this->assertTrue($row->_relationship_entities['parent'] instanceof TermInterface);
$this->assertEqual($row->_relationship_entities['parent']->id(), $this->term2->id());
$this->assertEqual($row->taxonomy_term_field_data_taxonomy_term_hierarchy_tid, $this->term2->id());
}
$this->assertTrue($row->_relationship_entities['nid'] instanceof NodeInterface);
$this->assertEqual($row->_relationship_entities['nid']->id(), $this->nodes[$index]->id());
}
}
}

View file

@ -0,0 +1,59 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
/**
* Tests the taxonomy term with depth argument.
*
* @group taxonomy
*/
class TaxonomyTermArgumentDepthTest extends TaxonomyTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['taxonomy', 'taxonomy_test_views', 'views', 'node'];
/**
* {@inheritdoc}
*/
public static $testViews = ['test_argument_taxonomy_index_tid_depth'];
/**
* @var \Drupal\taxonomy\TermInterface[]
*/
protected $terms = [];
/**
* @var \Drupal\views\ViewExecutable
*/
protected $view;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create a term with markup in the label.
$first = $this->createTerm(['name' => '<em>First</em>']);
// Create a node w/o any terms.
$settings = ['type' => 'article'];
// Create a node with linked to the term.
$settings['field_views_testing_tags'][0]['target_id'] = $first->id();
$this->nodes[] = $this->drupalCreateNode($settings);
$this->terms[0] = $first;
}
/**
* Tests title escaping.
*/
public function testTermWithDepthArgumentTitleEscaping() {
$this->drupalGet('test_argument_taxonomy_index_tid_depth/' . $this->terms[0]->id());
$this->assertEscaped($this->terms[0]->label());
}
}

View file

@ -0,0 +1,136 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\views\Views;
/**
* Test the taxonomy term with depth filter.
*
* @group taxonomy
*/
class TaxonomyTermFilterDepthTest extends TaxonomyTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['taxonomy', 'taxonomy_test_views', 'views', 'node'];
/**
* {@inheritdoc}
*/
public static $testViews = ['test_filter_taxonomy_index_tid_depth'];
/**
* @var \Drupal\taxonomy\TermInterface[]
*/
protected $terms = [];
/**
* @var \Drupal\views\ViewExecutable
*/
protected $view;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create a hierarchy 3 deep. Note the parent setup function creates two
// top-level terms w/o children.
$first = $this->createTerm(['name' => 'First']);
$second = $this->createTerm(['name' => 'Second', 'parent' => $first->id()]);
$third = $this->createTerm(['name' => 'Third', 'parent' => $second->id()]);
// Create a node w/o any terms.
$settings = ['type' => 'article'];
$this->nodes[] = $this->drupalCreateNode($settings);
// Create a node with only the top level term.
$settings['field_views_testing_tags'][0]['target_id'] = $first->id();
$this->nodes[] = $this->drupalCreateNode($settings);
// Create a node with only the third level term.
$settings['field_views_testing_tags'][0]['target_id'] = $third->id();
$this->nodes[] = $this->drupalCreateNode($settings);
$this->terms[0] = $first;
$this->terms[1] = $second;
$this->terms[2] = $third;
$this->view = Views::getView('test_filter_taxonomy_index_tid_depth');
}
/**
* Tests the terms with depth filter.
*/
public function testTermWithDepthFilter() {
$column_map = ['nid' => 'nid'];
$assert_method = 'assertIdentical';
// Default view has an empty value for this filter, so all nodes should be
// returned.
$expected = [
['nid' => 1],
['nid' => 2],
['nid' => 3],
['nid' => 4],
['nid' => 5],
];
$this->executeView($this->view);
$this->assertIdenticalResultsetHelper($this->view, $expected, $column_map, $assert_method);
// Set filter to search on top-level term, with depth 0.
$expected = [['nid' => 4]];
$this->assertTermWithDepthResult($this->terms[0]->id(), 0, $expected);
// Top-level term, depth 1.
$expected = [['nid' => 4]];
$this->assertTermWithDepthResult($this->terms[0]->id(), 0, $expected);
// Top-level term, depth 2.
$expected = [['nid' => 4], ['nid' => 5]];
$this->assertTermWithDepthResult($this->terms[0]->id(), 2, $expected);
// Second-level term, depth 1.
$expected = [['nid' => 5]];
$this->assertTermWithDepthResult($this->terms[1]->id(), 1, $expected);
// Third-level term, depth 0.
$expected = [['nid' => 5]];
$this->assertTermWithDepthResult($this->terms[2]->id(), 0, $expected);
// Third-level term, depth 1.
$expected = [['nid' => 5]];
$this->assertTermWithDepthResult($this->terms[2]->id(), 1, $expected);
// Third-level term, depth -2.
$expected = [['nid' => 4], ['nid' => 5]];
$this->assertTermWithDepthResult($this->terms[2]->id(), -2, $expected);
}
/**
* Changes the tid filter to given term and depth.
*
* @param int $tid
* The term ID to filter on.
* @param int $depth
* The depth to search.
* @param array $expected
* The expected views result.
*/
protected function assertTermWithDepthResult($tid, $depth, array $expected) {
$this->view->destroy();
$this->view->initDisplay();
$filters = $this->view->displayHandlers->get('default')
->getOption('filters');
$filters['tid_depth']['depth'] = $depth;
$filters['tid_depth']['value'] = [$tid];
$this->view->displayHandlers->get('default')
->setOption('filters', $filters);
$this->executeView($this->view);
$this->assertIdenticalResultsetHelper($this->view, $expected, ['nid' => 'nid'], 'assertIdentical');
}
}

View file

@ -0,0 +1,156 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
use Drupal\views\Views;
/**
* Tests the taxonomy term view page and its translation.
*
* @group taxonomy
*/
class TaxonomyTermViewTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('taxonomy', 'views');
/**
* An user with permissions to administer taxonomy.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* Name of the taxonomy term reference field.
*
* @var string
*/
protected $fieldName1;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create an administrative user.
$this->adminUser = $this->drupalCreateUser(['administer taxonomy', 'bypass node access']);
$this->drupalLogin($this->adminUser);
// Create a vocabulary and add two term reference fields to article nodes.
$this->fieldName1 = Unicode::strtolower($this->randomMachineName());
$handler_settings = array(
'target_bundles' => array(
$this->vocabulary->id() => $this->vocabulary->id(),
),
'auto_create' => TRUE,
);
$this->createEntityReferenceField('node', 'article', $this->fieldName1, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
entity_get_form_display('node', 'article', 'default')
->setComponent($this->fieldName1, array(
'type' => 'options_select',
))
->save();
entity_get_display('node', 'article', 'default')
->setComponent($this->fieldName1, array(
'type' => 'entity_reference_label',
))
->save();
}
/**
* Tests that the taxonomy term view is working properly.
*/
public function testTaxonomyTermView() {
// Create terms in the vocabulary.
$term = $this->createTerm();
// Post an article.
$edit = array();
$edit['title[0][value]'] = $original_title = $this->randomMachineName();
$edit['body[0][value]'] = $this->randomMachineName();
$edit["{$this->fieldName1}[]"] = $term->id();
$this->drupalPostForm('node/add/article', $edit, t('Save'));
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$this->drupalGet('taxonomy/term/' . $term->id());
$this->assertText($term->label());
$this->assertText($node->label());
\Drupal::service('module_installer')->install(array('language', 'content_translation'));
$language = ConfigurableLanguage::createFromLangcode('ur');
$language->save();
// Enable translation for the article content type and ensure the change is
// picked up.
\Drupal::service('content_translation.manager')->setEnabled('node', 'article', TRUE);
$roles = $this->adminUser->getRoles(TRUE);
Role::load(reset($roles))
->grantPermission('create content translations')
->grantPermission('translate any entity')
->save();
drupal_static_reset();
\Drupal::entityManager()->clearCachedDefinitions();
\Drupal::service('router.builder')->rebuild();
\Drupal::service('entity.definition_update_manager')->applyUpdates();
$edit['title[0][value]'] = $translated_title = $this->randomMachineName();
$this->drupalPostForm('node/' . $node->id() . '/translations/add/en/ur', $edit, t('Save (this translation)'));
$this->drupalGet('taxonomy/term/' . $term->id());
$this->assertText($term->label());
$this->assertText($original_title);
$this->assertNoText($translated_title);
$this->drupalGet('ur/taxonomy/term/' . $term->id());
$this->assertText($term->label());
$this->assertNoText($original_title);
$this->assertText($translated_title);
// Uninstall language module and ensure that the language is not part of the
// query anymore.
// @see \Drupal\views\Plugin\views\filter\LanguageFilter::query()
$node->delete();
\Drupal::service('module_installer')->uninstall(['content_translation', 'language']);
$view = Views::getView('taxonomy_term');
$view->initDisplay();
$view->setArguments([$term->id()]);
$view->build();
/** @var \Drupal\Core\Database\Query\Select $query */
$query = $view->build_info['query'];
$tables = $query->getTables();
// Ensure that the join to node_field_data is not added by default.
$this->assertEqual(['node_field_data', 'taxonomy_index'], array_keys($tables));
// Ensure that the filter to the language column is not there by default.
$condition = $query->conditions();
// We only want to check the no. of conditions in the query.
unset($condition['#conjunction']);
$this->assertEqual(1, count($condition));
// Clear permissions for anonymous users to check access for default views.
Role::load(RoleInterface::ANONYMOUS_ID)->revokePermission('access content')->save();
// Test the default views disclose no data by default.
$this->drupalLogout();
$this->drupalGet('taxonomy/term/' . $term->id());
$this->assertResponse(403);
$this->drupalGet('taxonomy/term/' . $term->id() . '/feed');
$this->assertResponse(403);
}
}

View file

@ -0,0 +1,155 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\views\Tests\ViewTestBase;
use Drupal\views\Tests\ViewTestData;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\Entity\Term;
/**
* Base class for all taxonomy tests.
*/
abstract class TaxonomyTestBase extends ViewTestBase {
use EntityReferenceTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('taxonomy', 'taxonomy_test_views');
/**
* Stores the nodes used for the different tests.
*
* @var \Drupal\node\NodeInterface[]
*/
protected $nodes = array();
/**
* The vocabulary used for creating terms.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* Stores the first term used in the different tests.
*
* @var \Drupal\taxonomy\TermInterface
*/
protected $term1;
/**
* Stores the second term used in the different tests.
*
* @var \Drupal\taxonomy\TermInterface
*/
protected $term2;
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$this->mockStandardInstall();
if ($import_test_views) {
ViewTestData::createTestViews(get_class($this), array('taxonomy_test_views'));
}
$this->term1 = $this->createTerm();
$this->term2 = $this->createTerm();
$node = array();
$node['type'] = 'article';
$node['field_views_testing_tags'][]['target_id'] = $this->term1->id();
$node['field_views_testing_tags'][]['target_id'] = $this->term2->id();
$this->nodes[] = $this->drupalCreateNode($node);
$this->nodes[] = $this->drupalCreateNode($node);
}
/**
* Provides a workaround for the inability to use the standard profile.
*
* @see https://www.drupal.org/node/1708692
*/
protected function mockStandardInstall() {
$this->drupalCreateContentType(array(
'type' => 'article',
));
// Create the vocabulary for the tag field.
$this->vocabulary = Vocabulary::create([
'name' => 'Views testing tags',
'vid' => 'views_testing_tags',
]);
$this->vocabulary->save();
$field_name = 'field_' . $this->vocabulary->id();
$handler_settings = array(
'target_bundles' => array(
$this->vocabulary->id() => $this->vocabulary->id(),
),
'auto_create' => TRUE,
);
$this->createEntityReferenceField('node', 'article', $field_name, 'Tags', 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
entity_get_form_display('node', 'article', 'default')
->setComponent($field_name, array(
'type' => 'entity_reference_autocomplete_tags',
'weight' => -4,
))
->save();
entity_get_display('node', 'article', 'default')
->setComponent($field_name, array(
'type' => 'entity_reference_label',
'weight' => 10,
))
->save();
entity_get_display('node', 'article', 'teaser')
->setComponent($field_name, array(
'type' => 'entity_reference_label',
'weight' => 10,
))
->save();
}
/**
* Creates and returns a taxonomy term.
*
* @param array $settings
* (optional) An array of values to override the following default
* properties of the term:
* - name: A random string.
* - description: A random string.
* - format: First available text format.
* - vid: Vocabulary ID of self::$vocabulary object.
* - langcode: LANGCODE_NOT_SPECIFIED.
* Defaults to an empty array.
*
* @return \Drupal\taxonomy\Entity\Term
* The created taxonomy term.
*/
protected function createTerm(array $settings = []) {
$filter_formats = filter_formats();
$format = array_pop($filter_formats);
$settings += [
'name' => $this->randomMachineName(),
'description' => $this->randomMachineName(),
// Use the first available text format.
'format' => $format->id(),
'vid' => $this->vocabulary->id(),
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
];
$term = Term::create($settings);
$term->save();
return $term;
}
}

View file

@ -0,0 +1,48 @@
<?php
namespace Drupal\taxonomy\Tests\Views;
use Drupal\views\Views;
/**
* Tests the term_name field handler.
*
* @group taxonomy
*
* @see \Drupal\taxonomy\Plugin\views\field\TermName
*/
class TermNameFieldTest extends TaxonomyTestBase {
/**
* {@inheritdoc}
*/
public static $testViews = array('test_taxonomy_term_name');
/**
* Tests term name field plugin functionality.
*/
public function testTermNameField() {
$this->term1->name->value = $this->randomMachineName() . ' ' . $this->randomMachineName();
$this->term1->save();
$user = $this->drupalCreateUser(['access content']);
$this->drupalLogin($user);
$view = Views::getView('test_taxonomy_term_name');
$view->initDisplay();
$this->executeView($view);
$this->assertEqual($this->term1->getName(), $view->getStyle()->getField(0, 'name'));
$this->assertEqual($this->term2->getName(), $view->getStyle()->getField(1, 'name'));
$view = Views::getView('test_taxonomy_term_name');
$display =& $view->storage->getDisplay('default');
$display['display_options']['fields']['name']['convert_spaces'] = TRUE;
$view->storage->invalidateCaches();
$this->executeView($view);
$this->assertEqual(str_replace(' ', '-', $this->term1->getName()), $view->getStyle()->getField(0, 'name'));
$this->assertEqual($this->term2->getName(), $view->getStyle()->getField(1, 'name'));
}
}

View file

@ -0,0 +1,182 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\field\Entity\FieldConfig;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\field\Entity\FieldStorageConfig;
/**
* Tests loading, saving and deleting vocabularies.
*
* @group taxonomy
*/
class VocabularyCrudTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('field_test', 'taxonomy_crud');
protected function setUp() {
parent::setUp();
$admin_user = $this->drupalCreateUser(array('create article content', 'administer taxonomy'));
$this->drupalLogin($admin_user);
$this->vocabulary = $this->createVocabulary();
}
/**
* Test deleting a taxonomy that contains terms.
*/
function testTaxonomyVocabularyDeleteWithTerms() {
// Delete any existing vocabularies.
foreach (Vocabulary::loadMultiple() as $vocabulary) {
$vocabulary->delete();
}
$query = \Drupal::entityQuery('taxonomy_term')->count();
// Assert that there are no terms left.
$this->assertEqual(0, $query->execute(), 'There are no terms remaining.');
$terms = array();
for ($i = 0; $i < 5; $i++) {
$terms[$i] = $this->createTerm($vocabulary);
}
// Set up hierarchy. term 2 is a child of 1 and 4 a child of 1 and 2.
$terms[2]->parent = array($terms[1]->id());
$terms[2]->save();
$terms[4]->parent = array($terms[1]->id(), $terms[2]->id());
$terms[4]->save();
// Assert that there are now 5 terms.
$this->assertEqual(5, $query->execute(), 'There are 5 terms found.');
$vocabulary->delete();
// Assert that there are no terms left.
$this->assertEqual(0, $query->execute(), 'All terms are deleted.');
}
/**
* Ensure that the vocabulary static reset works correctly.
*/
function testTaxonomyVocabularyLoadStaticReset() {
$original_vocabulary = Vocabulary::load($this->vocabulary->id());
$this->assertTrue(is_object($original_vocabulary), 'Vocabulary loaded successfully.');
$this->assertEqual($this->vocabulary->label(), $original_vocabulary->label(), 'Vocabulary loaded successfully.');
// Change the name and description.
$vocabulary = $original_vocabulary;
$vocabulary->set('name', $this->randomMachineName());
$vocabulary->set('description', $this->randomMachineName());
$vocabulary->save();
// Load the vocabulary.
$new_vocabulary = Vocabulary::load($original_vocabulary->id());
$this->assertEqual($new_vocabulary->label(), $vocabulary->label(), 'The vocabulary was loaded.');
// Delete the vocabulary.
$this->vocabulary->delete();
$vocabularies = Vocabulary::loadMultiple();
$this->assertTrue(!isset($vocabularies[$this->vocabulary->id()]), 'The vocabulary was deleted.');
}
/**
* Tests for loading multiple vocabularies.
*/
function testTaxonomyVocabularyLoadMultiple() {
// Delete any existing vocabularies.
foreach (Vocabulary::loadMultiple() as $vocabulary) {
$vocabulary->delete();
}
// Create some vocabularies and assign weights.
$vocabulary1 = $this->createVocabulary();
$vocabulary1->set('weight', 0);
$vocabulary1->save();
$vocabulary2 = $this->createVocabulary();
$vocabulary2->set('weight', 1);
$vocabulary2->save();
$vocabulary3 = $this->createVocabulary();
$vocabulary3->set('weight', 2);
$vocabulary3->save();
// Check if third party settings exist.
$this->assertEqual('bar', $vocabulary1->getThirdPartySetting('taxonomy_crud', 'foo'), 'Third party settings were added to the vocabulary.');
$this->assertEqual('bar', $vocabulary2->getThirdPartySetting('taxonomy_crud', 'foo'), 'Third party settings were added to the vocabulary.');
$this->assertEqual('bar', $vocabulary3->getThirdPartySetting('taxonomy_crud', 'foo'), 'Third party settings were added to the vocabulary.');
// Fetch the names for all vocabularies, confirm that they are keyed by
// machine name.
$names = taxonomy_vocabulary_get_names();
$this->assertEqual($names[$vocabulary1->id()], $vocabulary1->id(), 'Vocabulary 1 name found.');
// Fetch the vocabularies with entity_load_multiple(), specifying IDs.
// Ensure they are returned in the same order as the original array.
$vocabularies = Vocabulary::loadMultiple(array($vocabulary3->id(), $vocabulary2->id(), $vocabulary1->id()));
$loaded_order = array_keys($vocabularies);
$expected_order = array($vocabulary3->id(), $vocabulary2->id(), $vocabulary1->id());
$this->assertIdentical($loaded_order, $expected_order);
// Test loading vocabularies by their properties.
$controller = $this->container->get('entity.manager')->getStorage('taxonomy_vocabulary');
// Fetch vocabulary 1 by name.
$vocabulary = current($controller->loadByProperties(array('name' => $vocabulary1->label())));
$this->assertEqual($vocabulary->id(), $vocabulary1->id(), 'Vocabulary loaded successfully by name.');
// Fetch vocabulary 2 by name and ID.
$vocabulary = current($controller->loadByProperties(array(
'name' => $vocabulary2->label(),
'vid' => $vocabulary2->id(),
)));
$this->assertEqual($vocabulary->id(), $vocabulary2->id(), 'Vocabulary loaded successfully by name and ID.');
}
/**
* Test uninstall and reinstall of the taxonomy module.
*/
function testUninstallReinstall() {
// Field storages and fields attached to taxonomy term bundles should be
// removed when the module is uninstalled.
$field_name = Unicode::strtolower($this->randomMachineName() . '_field_name');
$storage_definition = array(
'field_name' => $field_name,
'entity_type' => 'taxonomy_term',
'type' => 'text',
'cardinality' => 4
);
FieldStorageConfig::create($storage_definition)->save();
$field_definition = array(
'field_name' => $field_name,
'entity_type' => 'taxonomy_term',
'bundle' => $this->vocabulary->id(),
'label' => $this->randomMachineName() . '_label',
);
FieldConfig::create($field_definition)->save();
// Remove the third party setting from the memory copy of the vocabulary.
// We keep this invalid copy around while the taxonomy module is not even
// installed for testing below.
$this->vocabulary->unsetThirdPartySetting('taxonomy_crud', 'foo');
require_once \Drupal::root() . '/core/includes/install.inc';
$this->container->get('module_installer')->uninstall(array('taxonomy'));
$this->container->get('module_installer')->install(array('taxonomy'));
// Now create a vocabulary with the same name. All fields
// connected to this vocabulary name should have been removed when the
// module was uninstalled. Creating a new field with the same name and
// an instance of this field on the same bundle name should be successful.
$this->vocabulary->enforceIsNew();
$this->vocabulary->save();
FieldStorageConfig::create($storage_definition)->save();
FieldConfig::create($field_definition)->save();
}
}

View file

@ -0,0 +1,125 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\language\Entity\ContentLanguageSettings;
/**
* Tests the language functionality for vocabularies.
*
* @group taxonomy
*/
class VocabularyLanguageTest extends TaxonomyTestBase {
public static $modules = array('language');
protected function setUp() {
parent::setUp();
// Create an administrative user.
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy']));
// Add some custom languages.
ConfigurableLanguage::create(array(
'id' => 'aa',
'label' => $this->randomMachineName(),
))->save();
ConfigurableLanguage::create(array(
'id' => 'bb',
'label' => $this->randomMachineName(),
))->save();
}
/**
* Tests language settings for vocabularies.
*/
function testVocabularyLanguage() {
$this->drupalGet('admin/structure/taxonomy/add');
// Check that we have the language selector available.
$this->assertField('edit-langcode', 'The language selector field was found on the page.');
// Create the vocabulary.
$vid = Unicode::strtolower($this->randomMachineName());
$edit['name'] = $this->randomMachineName();
$edit['description'] = $this->randomMachineName();
$edit['langcode'] = 'aa';
$edit['vid'] = $vid;
$this->drupalPostForm(NULL, $edit, t('Save'));
// Check the language on the edit page.
$this->drupalGet('admin/structure/taxonomy/manage/' . $vid);
$this->assertOptionSelected('edit-langcode', $edit['langcode'], 'The vocabulary language was correctly selected.');
// Change the language and save again.
$edit['langcode'] = 'bb';
unset($edit['vid']);
$this->drupalPostForm(NULL, $edit, t('Save'));
// Check again the language on the edit page.
$this->drupalGet('admin/structure/taxonomy/manage/' . $vid);
$this->assertOptionSelected('edit-langcode', $edit['langcode'], 'The vocabulary language was correctly selected.');
}
/**
* Tests term language settings for vocabulary terms are saved and updated.
*/
function testVocabularyDefaultLanguageForTerms() {
// Add a new vocabulary and check that the default language settings are for
// the terms are saved.
$edit = array(
'name' => $this->randomMachineName(),
'vid' => Unicode::strtolower($this->randomMachineName()),
'default_language[langcode]' => 'bb',
'default_language[language_alterable]' => TRUE,
);
$vid = $edit['vid'];
$this->drupalPostForm('admin/structure/taxonomy/add', $edit, t('Save'));
// Check that the vocabulary was actually created.
$this->drupalGet('admin/structure/taxonomy/manage/' . $edit['vid']);
$this->assertResponse(200, 'The vocabulary has been created.');
// Check that the language settings were saved.
$language_settings = ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', $edit['vid']);
$this->assertEqual($language_settings->getDefaultLangcode(), 'bb', 'The langcode was saved.');
$this->assertTrue($language_settings->isLanguageAlterable(), 'The visibility setting was saved.');
// Check that the correct options are selected in the interface.
$this->assertOptionSelected('edit-default-language-langcode', 'bb', 'The correct default language for the terms of this vocabulary is selected.');
$this->assertFieldChecked('edit-default-language-language-alterable', 'Show language selection option is checked.');
// Edit the vocabulary and check that the new settings are updated.
$edit = array(
'default_language[langcode]' => 'aa',
'default_language[language_alterable]' => FALSE,
);
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $vid, $edit, t('Save'));
// And check again the settings and also the interface.
$language_settings = ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', $vid);
$this->assertEqual($language_settings->getDefaultLangcode(), 'aa', 'The langcode was saved.');
$this->assertFalse($language_settings->isLanguageAlterable(), 'The visibility setting was saved.');
$this->drupalGet('admin/structure/taxonomy/manage/' . $vid);
$this->assertOptionSelected('edit-default-language-langcode', 'aa', 'The correct default language for the terms of this vocabulary is selected.');
$this->assertNoFieldChecked('edit-default-language-language-alterable', 'Show language selection option is not checked.');
// Check that language settings are changed after editing vocabulary.
$edit = array(
'name' => $this->randomMachineName(),
'default_language[langcode]' => 'authors_default',
'default_language[language_alterable]' => FALSE,
);
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $vid, $edit, t('Save'));
// Check that we have the new settings.
$new_settings = ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', $vid);
$this->assertEqual($new_settings->getDefaultLangcode(), 'authors_default', 'The langcode was saved.');
$this->assertFalse($new_settings->isLanguageAlterable(), 'The new visibility setting was saved.');
}
}

View file

@ -0,0 +1,136 @@
<?php
namespace Drupal\taxonomy\Tests;
/**
* Tests the taxonomy vocabulary permissions.
*
* @group taxonomy
*/
class VocabularyPermissionsTest extends TaxonomyTestBase {
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('page_title_block');
}
/**
* Create, edit and delete a taxonomy term via the user interface.
*/
function testVocabularyPermissionsTaxonomyTerm() {
// Vocabulary used for creating, removing and editing terms.
$vocabulary = $this->createVocabulary();
// Test as admin user.
$user = $this->drupalCreateUser(array('administer taxonomy'));
$this->drupalLogin($user);
// Visit the main taxonomy administration page.
$this->drupalGet('admin/structure/taxonomy/manage/' . $vocabulary->id() . '/add');
$this->assertResponse(200);
$this->assertField('edit-name-0-value', 'Add taxonomy term form opened successfully.');
// Submit the term.
$edit = array();
$edit['name[0][value]'] = $this->randomMachineName();
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertText(t('Created new term @name.', array('@name' => $edit['name[0][value]'])), 'Term created successfully.');
// Verify that the creation message contains a link to a term.
$view_link = $this->xpath('//div[@class="messages"]//a[contains(@href, :href)]', array(':href' => 'term/'));
$this->assert(isset($view_link), 'The message area contains a link to a term');
$terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']);
$term = reset($terms);
// Edit the term.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$this->assertResponse(200);
$this->assertText($edit['name[0][value]'], 'Edit taxonomy term form opened successfully.');
$edit['name[0][value]'] = $this->randomMachineName();
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertText(t('Updated term @name.', array('@name' => $edit['name[0][value]'])), 'Term updated successfully.');
// Delete the vocabulary.
$this->drupalGet('taxonomy/term/' . $term->id() . '/delete');
$this->assertRaw(t('Are you sure you want to delete the @entity-type %label?', array('@entity-type' => 'taxonomy term', '%label' => $edit['name[0][value]'])), 'Delete taxonomy term form opened successfully.');
// Confirm deletion.
$this->drupalPostForm(NULL, NULL, t('Delete'));
$this->assertRaw(t('Deleted term %name.', array('%name' => $edit['name[0][value]'])), 'Term deleted.');
// Test as user with "edit" permissions.
$user = $this->drupalCreateUser(array("edit terms in {$vocabulary->id()}"));
$this->drupalLogin($user);
// Visit the main taxonomy administration page.
$this->drupalGet('admin/structure/taxonomy/manage/' . $vocabulary->id() . '/add');
$this->assertResponse(403, 'Add taxonomy term form open failed.');
// Create a test term.
$term = $this->createTerm($vocabulary);
// Edit the term.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$this->assertResponse(200);
$this->assertText($term->getName(), 'Edit taxonomy term form opened successfully.');
$edit['name[0][value]'] = $this->randomMachineName();
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertText(t('Updated term @name.', array('@name' => $edit['name[0][value]'])), 'Term updated successfully.');
// Verify that the update message contains a link to a term.
$view_link = $this->xpath('//div[@class="messages"]//a[contains(@href, :href)]', array(':href' => 'term/'));
$this->assert(isset($view_link), 'The message area contains a link to a term');
// Delete the vocabulary.
$this->drupalGet('taxonomy/term/' . $term->id() . '/delete');
$this->assertResponse(403, 'Delete taxonomy term form open failed.');
// Test as user with "delete" permissions.
$user = $this->drupalCreateUser(array("delete terms in {$vocabulary->id()}"));
$this->drupalLogin($user);
// Visit the main taxonomy administration page.
$this->drupalGet('admin/structure/taxonomy/manage/' . $vocabulary->id() . '/add');
$this->assertResponse(403, 'Add taxonomy term form open failed.');
// Create a test term.
$term = $this->createTerm($vocabulary);
// Edit the term.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$this->assertResponse(403, 'Edit taxonomy term form open failed.');
// Delete the vocabulary.
$this->drupalGet('taxonomy/term/' . $term->id() . '/delete');
$this->assertRaw(t('Are you sure you want to delete the @entity-type %label?', array('@entity-type' => 'taxonomy term', '%label' => $term->getName())), 'Delete taxonomy term form opened successfully.');
// Confirm deletion.
$this->drupalPostForm(NULL, NULL, t('Delete'));
$this->assertRaw(t('Deleted term %name.', array('%name' => $term->getName())), 'Term deleted.');
// Test as user without proper permissions.
$user = $this->drupalCreateUser();
$this->drupalLogin($user);
// Visit the main taxonomy administration page.
$this->drupalGet('admin/structure/taxonomy/manage/' . $vocabulary->id() . '/add');
$this->assertResponse(403, 'Add taxonomy term form open failed.');
// Create a test term.
$term = $this->createTerm($vocabulary);
// Edit the term.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$this->assertResponse(403, 'Edit taxonomy term form open failed.');
// Delete the vocabulary.
$this->drupalGet('taxonomy/term/' . $term->id() . '/delete');
$this->assertResponse(403, 'Delete taxonomy term form open failed.');
}
}

View file

@ -0,0 +1,55 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Component\Utility\Unicode;
/**
* Tests content translation for vocabularies.
*
* @group taxonomy
*/
class VocabularyTranslationTest extends TaxonomyTestBase {
/**
* {@inheritdoc}
*/
public static $modules = array('content_translation', 'language');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create an administrative user.
$this->drupalLogin($this->drupalCreateUser([
'administer taxonomy',
'administer content translation',
]));
}
/**
* Tests language settings for vocabularies.
*/
function testVocabularyLanguage() {
$this->drupalGet('admin/structure/taxonomy/add');
// Check that the field to enable content translation is available.
$this->assertField('edit-default-language-content-translation', 'The content translation checkbox is present on the page.');
// Create the vocabulary.
$vid = Unicode::strtolower($this->randomMachineName());
$edit['name'] = $this->randomMachineName();
$edit['description'] = $this->randomMachineName();
$edit['langcode'] = 'en';
$edit['vid'] = $vid;
$edit['default_language[content_translation]'] = TRUE;
$this->drupalPostForm(NULL, $edit, t('Save'));
// Check if content translation is enabled on the edit page.
$this->drupalGet('admin/structure/taxonomy/manage/' . $vid);
$this->assertFieldChecked('edit-default-language-content-translation', 'The content translation was correctly selected.');
}
}

View file

@ -0,0 +1,157 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Url;
use Drupal\taxonomy\Entity\Vocabulary;
/**
* Tests the taxonomy vocabulary interface.
*
* @group taxonomy
*/
class VocabularyUiTest extends TaxonomyTestBase {
/**
* The vocabulary used for creating terms.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy']));
$this->vocabulary = $this->createVocabulary();
$this->drupalPlaceBlock('local_actions_block');
$this->drupalPlaceBlock('page_title_block');
}
/**
* Create, edit and delete a vocabulary via the user interface.
*/
function testVocabularyInterface() {
// Visit the main taxonomy administration page.
$this->drupalGet('admin/structure/taxonomy');
// Create a new vocabulary.
$this->clickLink(t('Add vocabulary'));
$edit = array();
$vid = Unicode::strtolower($this->randomMachineName());
$edit['name'] = $this->randomMachineName();
$edit['description'] = $this->randomMachineName();
$edit['vid'] = $vid;
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertRaw(t('Created new vocabulary %name.', array('%name' => $edit['name'])), 'Vocabulary created successfully.');
// Edit the vocabulary.
$this->drupalGet('admin/structure/taxonomy');
$this->assertText($edit['name'], 'Vocabulary found in the vocabulary overview listing.');
$this->assertLinkByHref(Url::fromRoute('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $edit['vid']])->toString());
$this->clickLink(t('Edit vocabulary'));
$edit = array();
$edit['name'] = $this->randomMachineName();
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->drupalGet('admin/structure/taxonomy');
$this->assertText($edit['name'], 'Vocabulary found in the vocabulary overview listing.');
// Try to submit a vocabulary with a duplicate machine name.
$edit['vid'] = $vid;
$this->drupalPostForm('admin/structure/taxonomy/add', $edit, t('Save'));
$this->assertText(t('The machine-readable name is already in use. It must be unique.'));
// Try to submit an invalid machine name.
$edit['vid'] = '!&^%';
$this->drupalPostForm('admin/structure/taxonomy/add', $edit, t('Save'));
$this->assertText(t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
// Ensure that vocabulary titles are escaped properly.
$edit = array();
$edit['name'] = 'Don\'t Panic';
$edit['description'] = $this->randomMachineName();
$edit['vid'] = 'don_t_panic';
$this->drupalPostForm('admin/structure/taxonomy/add', $edit, t('Save'));
$site_name = $this->config('system.site')->get('name');
$this->assertTitle(t('Don\'t Panic | @site-name', array('@site-name' => $site_name)), 'The page title contains the escaped character.');
$this->assertNoTitle(t('Don&#039;t Panic | @site-name', array('@site-name' => $site_name)), 'The page title does not contain an encoded character.');
}
/**
* Changing weights on the vocabulary overview with two or more vocabularies.
*/
function testTaxonomyAdminChangingWeights() {
// Create some vocabularies.
for ($i = 0; $i < 10; $i++) {
$this->createVocabulary();
}
// Get all vocabularies and change their weights.
$vocabularies = Vocabulary::loadMultiple();
$edit = array();
foreach ($vocabularies as $key => $vocabulary) {
$weight = -$vocabulary->get('weight');
$vocabularies[$key]->set('weight', $weight);
$edit['vocabularies[' . $key . '][weight]'] = $weight;
}
// Saving the new weights via the interface.
$this->drupalPostForm('admin/structure/taxonomy', $edit, t('Save'));
// Load the vocabularies from the database.
$this->container->get('entity.manager')->getStorage('taxonomy_vocabulary')->resetCache();
$new_vocabularies = Vocabulary::loadMultiple();
// Check that the weights are saved in the database correctly.
foreach ($vocabularies as $key => $vocabulary) {
$this->assertEqual($new_vocabularies[$key]->get('weight'), $vocabularies[$key]->get('weight'), 'The vocabulary weight was changed.');
}
}
/**
* Test the vocabulary overview with no vocabularies.
*/
function testTaxonomyAdminNoVocabularies() {
// Delete all vocabularies.
$vocabularies = Vocabulary::loadMultiple();
foreach ($vocabularies as $key => $vocabulary) {
$vocabulary->delete();
}
// Confirm that no vocabularies are found in the database.
$this->assertFalse(Vocabulary::loadMultiple(), 'No vocabularies found.');
$this->drupalGet('admin/structure/taxonomy');
// Check the default message for no vocabularies.
$this->assertText(t('No vocabularies available.'));
}
/**
* Deleting a vocabulary.
*/
function testTaxonomyAdminDeletingVocabulary() {
// Create a vocabulary.
$vid = Unicode::strtolower($this->randomMachineName());
$edit = array(
'name' => $this->randomMachineName(),
'vid' => $vid,
);
$this->drupalPostForm('admin/structure/taxonomy/add', $edit, t('Save'));
$this->assertText(t('Created new vocabulary'), 'New vocabulary was created.');
// Check the created vocabulary.
$this->container->get('entity.manager')->getStorage('taxonomy_vocabulary')->resetCache();
$vocabulary = Vocabulary::load($vid);
$this->assertTrue($vocabulary, 'Vocabulary found.');
// Delete the vocabulary.
$this->drupalGet('admin/structure/taxonomy/manage/' . $vocabulary->id());
$this->clickLink(t('Delete'));
$this->assertRaw(t('Are you sure you want to delete the vocabulary %name?', array('%name' => $vocabulary->label())), '[confirm deletion] Asks for confirmation.');
$this->assertText(t('Deleting a vocabulary will delete all the terms in it. This action cannot be undone.'), '[confirm deletion] Inform that all terms will be deleted.');
// Confirm deletion.
$this->drupalPostForm(NULL, NULL, t('Delete'));
$this->assertRaw(t('Deleted vocabulary %name.', array('%name' => $vocabulary->label())), 'Vocabulary deleted.');
$this->container->get('entity.manager')->getStorage('taxonomy_vocabulary')->resetCache();
$this->assertFalse(Vocabulary::load($vid), 'Vocabulary not found.');
}
}