3 namespace Drupal\Tests\taxonomy\Functional;
5 use Drupal\Component\Serialization\Json;
6 use Drupal\Core\Entity\Entity\EntityFormDisplay;
7 use Drupal\Core\Entity\Entity\EntityViewDisplay;
8 use Drupal\Core\Field\FieldStorageDefinitionInterface;
9 use Drupal\field\Entity\FieldConfig;
10 use Drupal\field\Entity\FieldStorageConfig;
13 * Tests the autocomplete implementation of the taxonomy class.
17 class TermAutocompleteTest extends TaxonomyTestBase {
24 public static $modules = ['node'];
29 * @var \Drupal\taxonomy\Entity\Vocabulary
31 protected $vocabulary;
34 * The field to add to the content type for the taxonomy terms.
43 * @var \Drupal\user\Entity\User
48 * The autocomplete URL to call.
52 protected $autocompleteUrl;
55 * The term IDs indexed by term names.
64 protected function setUp() {
67 // Create a vocabulary.
68 $this->vocabulary = $this->createVocabulary();
70 // Create 11 terms, which have some sub-string in common, in a
71 // non-alphabetical order, so that we will have more than 10 matches later
72 // when we test the correct number of results is returned, and we can test
73 // the order of the results. The location of the sub-string to match varies
74 // also, since it should not be necessary to start with the sub-string to
75 // match it. Save term IDs to reuse later.
89 foreach ($termNames as $termName) {
90 $term = $this->createTerm($this->vocabulary, ['name' => $termName]);
91 $this->termIds[$termName] = $term->id();
94 // Create a taxonomy_term_reference field on the article Content Type that
95 // uses a taxonomy_autocomplete widget.
96 $this->fieldName = mb_strtolower($this->randomMachineName());
97 FieldStorageConfig::create([
98 'field_name' => $this->fieldName,
99 'entity_type' => 'node',
100 'type' => 'entity_reference',
101 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
103 'target_type' => 'taxonomy_term',
106 FieldConfig::create([
107 'field_name' => $this->fieldName,
108 'bundle' => 'article',
109 'entity_type' => 'node',
111 'handler' => 'default',
112 'handler_settings' => [
113 // Restrict selection of terms to a single vocabulary.
114 'target_bundles' => [
115 $this->vocabulary->id() => $this->vocabulary->id(),
120 EntityFormDisplay::load('node.article.default')
121 ->setComponent($this->fieldName, [
122 'type' => 'entity_reference_autocomplete',
125 EntityViewDisplay::load('node.article.default')
126 ->setComponent($this->fieldName, [
127 'type' => 'entity_reference_label',
131 // Create a user and then login.
132 $this->adminUser = $this->drupalCreateUser(['create article content']);
133 $this->drupalLogin($this->adminUser);
135 // Retrieve the autocomplete url.
136 $this->drupalGet('node/add/article');
137 $result = $this->xpath('//input[@name="' . $this->fieldName . '[0][target_id]"]');
138 $this->autocompleteUrl = $this->getAbsoluteUrl($result[0]->getAttribute('data-autocomplete-path'));
142 * Helper function for JSON formatted requests.
144 * @param string|\Drupal\Core\Url $path
145 * Drupal path or URL to load into Mink controlled browser.
146 * @param array $options
147 * (optional) Options to be forwarded to the url generator.
148 * @param string[] $headers
149 * (optional) An array containing additional HTTP request headers.
152 * Array representing decoded JSON response.
154 protected function drupalGetJson($path, array $options = [], array $headers = []) {
155 $options = array_merge_recursive(['query' => ['_format' => 'json']], $options);
156 return Json::decode($this->drupalGet($path, $options, $headers));
160 * Tests that the autocomplete method returns the good number of results.
162 * @see \Drupal\taxonomy\Controller\TermAutocompleteController::autocomplete()
164 public function testAutocompleteCountResults() {
165 // Test that no matching term found.
166 $data = $this->drupalGetJson(
167 $this->autocompleteUrl,
168 ['query' => ['q' => 'zzz']]
170 $this->assertTrue(empty($data), 'Autocomplete returned no results');
172 // Test that only one matching term found, when only one matches.
173 $data = $this->drupalGetJson(
174 $this->autocompleteUrl,
175 ['query' => ['q' => 'aaa 10']]
177 $this->assertEqual(1, count($data), 'Autocomplete returned 1 result');
179 // Test the correct number of matches when multiple are partial matches.
180 $data = $this->drupalGetJson(
181 $this->autocompleteUrl,
182 ['query' => ['q' => 'aaa 1']]
184 $this->assertEqual(3, count($data), 'Autocomplete returned 3 results');
186 // Tests that only 10 results are returned, even if there are more than 10
188 $data = $this->drupalGetJson(
189 $this->autocompleteUrl,
190 ['query' => ['q' => 'aaa']]
192 $this->assertEqual(10, count($data), 'Autocomplete returned only 10 results (for over 10 matches)');
196 * Tests that the autocomplete method returns properly ordered results.
198 * @see \Drupal\taxonomy\Controller\TermAutocompleteController::autocomplete()
200 public function testAutocompleteOrderedResults() {
212 // Build $expected to match the autocomplete results.
214 foreach ($expectedResults as $termName) {
216 'value' => $termName . ' (' . $this->termIds[$termName] . ')',
217 'label' => $termName,
221 $data = $this->drupalGetJson(
222 $this->autocompleteUrl,
223 ['query' => ['q' => 'bbb']]
226 $this->assertIdentical($expected, $data);