annotate core/modules/taxonomy/tests/src/Functional/TermAutocompleteTest.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@17 1 <?php
Chris@17 2
Chris@17 3 namespace Drupal\Tests\taxonomy\Functional;
Chris@17 4
Chris@17 5 use Drupal\Component\Serialization\Json;
Chris@17 6 use Drupal\Core\Entity\Entity\EntityFormDisplay;
Chris@17 7 use Drupal\Core\Entity\Entity\EntityViewDisplay;
Chris@17 8 use Drupal\Core\Field\FieldStorageDefinitionInterface;
Chris@17 9 use Drupal\field\Entity\FieldConfig;
Chris@17 10 use Drupal\field\Entity\FieldStorageConfig;
Chris@17 11
Chris@17 12 /**
Chris@17 13 * Tests the autocomplete implementation of the taxonomy class.
Chris@17 14 *
Chris@17 15 * @group taxonomy
Chris@17 16 */
Chris@17 17 class TermAutocompleteTest extends TaxonomyTestBase {
Chris@17 18
Chris@17 19 /**
Chris@17 20 * Modules to enable.
Chris@17 21 *
Chris@17 22 * @var array
Chris@17 23 */
Chris@17 24 public static $modules = ['node'];
Chris@17 25
Chris@17 26 /**
Chris@17 27 * The vocabulary.
Chris@17 28 *
Chris@17 29 * @var \Drupal\taxonomy\Entity\Vocabulary
Chris@17 30 */
Chris@17 31 protected $vocabulary;
Chris@17 32
Chris@17 33 /**
Chris@17 34 * The field to add to the content type for the taxonomy terms.
Chris@17 35 *
Chris@17 36 * @var string
Chris@17 37 */
Chris@17 38 protected $fieldName;
Chris@17 39
Chris@17 40 /**
Chris@17 41 * The admin user.
Chris@17 42 *
Chris@17 43 * @var \Drupal\user\Entity\User
Chris@17 44 */
Chris@17 45 protected $adminUser;
Chris@17 46
Chris@17 47 /**
Chris@17 48 * The autocomplete URL to call.
Chris@17 49 *
Chris@17 50 * @var string
Chris@17 51 */
Chris@17 52 protected $autocompleteUrl;
Chris@17 53
Chris@17 54 /**
Chris@17 55 * The term IDs indexed by term names.
Chris@17 56 *
Chris@17 57 * @var array
Chris@17 58 */
Chris@17 59 protected $termIds;
Chris@17 60
Chris@17 61 /**
Chris@17 62 * {@inheritdoc}
Chris@17 63 */
Chris@17 64 protected function setUp() {
Chris@17 65 parent::setUp();
Chris@17 66
Chris@17 67 // Create a vocabulary.
Chris@17 68 $this->vocabulary = $this->createVocabulary();
Chris@17 69
Chris@17 70 // Create 11 terms, which have some sub-string in common, in a
Chris@17 71 // non-alphabetical order, so that we will have more than 10 matches later
Chris@17 72 // when we test the correct number of results is returned, and we can test
Chris@17 73 // the order of the results. The location of the sub-string to match varies
Chris@17 74 // also, since it should not be necessary to start with the sub-string to
Chris@17 75 // match it. Save term IDs to reuse later.
Chris@17 76 $termNames = [
Chris@17 77 'aaa 20 bbb',
Chris@17 78 'aaa 70 bbb',
Chris@17 79 'aaa 10 bbb',
Chris@17 80 'aaa 12 bbb',
Chris@17 81 'aaa 40 bbb',
Chris@17 82 'aaa 11 bbb',
Chris@17 83 'aaa 30 bbb',
Chris@17 84 'aaa 50 bbb',
Chris@17 85 'aaa 80',
Chris@17 86 'aaa 90',
Chris@17 87 'bbb 60 aaa',
Chris@17 88 ];
Chris@17 89 foreach ($termNames as $termName) {
Chris@17 90 $term = $this->createTerm($this->vocabulary, ['name' => $termName]);
Chris@17 91 $this->termIds[$termName] = $term->id();
Chris@17 92 }
Chris@17 93
Chris@17 94 // Create a taxonomy_term_reference field on the article Content Type that
Chris@17 95 // uses a taxonomy_autocomplete widget.
Chris@17 96 $this->fieldName = mb_strtolower($this->randomMachineName());
Chris@17 97 FieldStorageConfig::create([
Chris@17 98 'field_name' => $this->fieldName,
Chris@17 99 'entity_type' => 'node',
Chris@17 100 'type' => 'entity_reference',
Chris@17 101 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
Chris@17 102 'settings' => [
Chris@17 103 'target_type' => 'taxonomy_term',
Chris@17 104 ],
Chris@17 105 ])->save();
Chris@17 106 FieldConfig::create([
Chris@17 107 'field_name' => $this->fieldName,
Chris@17 108 'bundle' => 'article',
Chris@17 109 'entity_type' => 'node',
Chris@17 110 'settings' => [
Chris@17 111 'handler' => 'default',
Chris@17 112 'handler_settings' => [
Chris@17 113 // Restrict selection of terms to a single vocabulary.
Chris@17 114 'target_bundles' => [
Chris@17 115 $this->vocabulary->id() => $this->vocabulary->id(),
Chris@17 116 ],
Chris@17 117 ],
Chris@17 118 ],
Chris@17 119 ])->save();
Chris@17 120 EntityFormDisplay::load('node.article.default')
Chris@17 121 ->setComponent($this->fieldName, [
Chris@17 122 'type' => 'entity_reference_autocomplete',
Chris@17 123 ])
Chris@17 124 ->save();
Chris@17 125 EntityViewDisplay::load('node.article.default')
Chris@17 126 ->setComponent($this->fieldName, [
Chris@17 127 'type' => 'entity_reference_label',
Chris@17 128 ])
Chris@17 129 ->save();
Chris@17 130
Chris@17 131 // Create a user and then login.
Chris@17 132 $this->adminUser = $this->drupalCreateUser(['create article content']);
Chris@17 133 $this->drupalLogin($this->adminUser);
Chris@17 134
Chris@17 135 // Retrieve the autocomplete url.
Chris@17 136 $this->drupalGet('node/add/article');
Chris@17 137 $result = $this->xpath('//input[@name="' . $this->fieldName . '[0][target_id]"]');
Chris@17 138 $this->autocompleteUrl = $this->getAbsoluteUrl($result[0]->getAttribute('data-autocomplete-path'));
Chris@17 139 }
Chris@17 140
Chris@17 141 /**
Chris@17 142 * Helper function for JSON formatted requests.
Chris@17 143 *
Chris@17 144 * @param string|\Drupal\Core\Url $path
Chris@17 145 * Drupal path or URL to load into Mink controlled browser.
Chris@17 146 * @param array $options
Chris@17 147 * (optional) Options to be forwarded to the url generator.
Chris@17 148 * @param string[] $headers
Chris@17 149 * (optional) An array containing additional HTTP request headers.
Chris@17 150 *
Chris@17 151 * @return string[]
Chris@17 152 * Array representing decoded JSON response.
Chris@17 153 */
Chris@17 154 protected function drupalGetJson($path, array $options = [], array $headers = []) {
Chris@17 155 $options = array_merge_recursive(['query' => ['_format' => 'json']], $options);
Chris@17 156 return Json::decode($this->drupalGet($path, $options, $headers));
Chris@17 157 }
Chris@17 158
Chris@17 159 /**
Chris@17 160 * Tests that the autocomplete method returns the good number of results.
Chris@17 161 *
Chris@17 162 * @see \Drupal\taxonomy\Controller\TermAutocompleteController::autocomplete()
Chris@17 163 */
Chris@17 164 public function testAutocompleteCountResults() {
Chris@17 165 // Test that no matching term found.
Chris@17 166 $data = $this->drupalGetJson(
Chris@17 167 $this->autocompleteUrl,
Chris@17 168 ['query' => ['q' => 'zzz']]
Chris@17 169 );
Chris@17 170 $this->assertTrue(empty($data), 'Autocomplete returned no results');
Chris@17 171
Chris@17 172 // Test that only one matching term found, when only one matches.
Chris@17 173 $data = $this->drupalGetJson(
Chris@17 174 $this->autocompleteUrl,
Chris@17 175 ['query' => ['q' => 'aaa 10']]
Chris@17 176 );
Chris@17 177 $this->assertEqual(1, count($data), 'Autocomplete returned 1 result');
Chris@17 178
Chris@17 179 // Test the correct number of matches when multiple are partial matches.
Chris@17 180 $data = $this->drupalGetJson(
Chris@17 181 $this->autocompleteUrl,
Chris@17 182 ['query' => ['q' => 'aaa 1']]
Chris@17 183 );
Chris@17 184 $this->assertEqual(3, count($data), 'Autocomplete returned 3 results');
Chris@17 185
Chris@17 186 // Tests that only 10 results are returned, even if there are more than 10
Chris@17 187 // matches.
Chris@17 188 $data = $this->drupalGetJson(
Chris@17 189 $this->autocompleteUrl,
Chris@17 190 ['query' => ['q' => 'aaa']]
Chris@17 191 );
Chris@17 192 $this->assertEqual(10, count($data), 'Autocomplete returned only 10 results (for over 10 matches)');
Chris@17 193 }
Chris@17 194
Chris@17 195 /**
Chris@17 196 * Tests that the autocomplete method returns properly ordered results.
Chris@17 197 *
Chris@17 198 * @see \Drupal\taxonomy\Controller\TermAutocompleteController::autocomplete()
Chris@17 199 */
Chris@17 200 public function testAutocompleteOrderedResults() {
Chris@17 201 $expectedResults = [
Chris@17 202 'aaa 10 bbb',
Chris@17 203 'aaa 11 bbb',
Chris@17 204 'aaa 12 bbb',
Chris@17 205 'aaa 20 bbb',
Chris@17 206 'aaa 30 bbb',
Chris@17 207 'aaa 40 bbb',
Chris@17 208 'aaa 50 bbb',
Chris@17 209 'aaa 70 bbb',
Chris@17 210 'bbb 60 aaa',
Chris@17 211 ];
Chris@17 212 // Build $expected to match the autocomplete results.
Chris@17 213 $expected = [];
Chris@17 214 foreach ($expectedResults as $termName) {
Chris@17 215 $expected[] = [
Chris@17 216 'value' => $termName . ' (' . $this->termIds[$termName] . ')',
Chris@17 217 'label' => $termName,
Chris@17 218 ];
Chris@17 219 }
Chris@17 220
Chris@17 221 $data = $this->drupalGetJson(
Chris@17 222 $this->autocompleteUrl,
Chris@17 223 ['query' => ['q' => 'bbb']]
Chris@17 224 );
Chris@17 225
Chris@17 226 $this->assertIdentical($expected, $data);
Chris@17 227 }
Chris@17 228
Chris@17 229 }