Chris@17: vocabulary = $this->createVocabulary(); Chris@17: Chris@17: // Create 11 terms, which have some sub-string in common, in a Chris@17: // non-alphabetical order, so that we will have more than 10 matches later Chris@17: // when we test the correct number of results is returned, and we can test Chris@17: // the order of the results. The location of the sub-string to match varies Chris@17: // also, since it should not be necessary to start with the sub-string to Chris@17: // match it. Save term IDs to reuse later. Chris@17: $termNames = [ Chris@17: 'aaa 20 bbb', Chris@17: 'aaa 70 bbb', Chris@17: 'aaa 10 bbb', Chris@17: 'aaa 12 bbb', Chris@17: 'aaa 40 bbb', Chris@17: 'aaa 11 bbb', Chris@17: 'aaa 30 bbb', Chris@17: 'aaa 50 bbb', Chris@17: 'aaa 80', Chris@17: 'aaa 90', Chris@17: 'bbb 60 aaa', Chris@17: ]; Chris@17: foreach ($termNames as $termName) { Chris@17: $term = $this->createTerm($this->vocabulary, ['name' => $termName]); Chris@17: $this->termIds[$termName] = $term->id(); Chris@17: } Chris@17: Chris@17: // Create a taxonomy_term_reference field on the article Content Type that Chris@17: // uses a taxonomy_autocomplete widget. Chris@17: $this->fieldName = mb_strtolower($this->randomMachineName()); Chris@17: FieldStorageConfig::create([ Chris@17: 'field_name' => $this->fieldName, Chris@17: 'entity_type' => 'node', Chris@17: 'type' => 'entity_reference', Chris@17: 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, Chris@17: 'settings' => [ Chris@17: 'target_type' => 'taxonomy_term', Chris@17: ], Chris@17: ])->save(); Chris@17: FieldConfig::create([ Chris@17: 'field_name' => $this->fieldName, Chris@17: 'bundle' => 'article', Chris@17: 'entity_type' => 'node', Chris@17: 'settings' => [ Chris@17: 'handler' => 'default', Chris@17: 'handler_settings' => [ Chris@17: // Restrict selection of terms to a single vocabulary. Chris@17: 'target_bundles' => [ Chris@17: $this->vocabulary->id() => $this->vocabulary->id(), Chris@17: ], Chris@17: ], Chris@17: ], Chris@17: ])->save(); Chris@17: EntityFormDisplay::load('node.article.default') Chris@17: ->setComponent($this->fieldName, [ Chris@17: 'type' => 'entity_reference_autocomplete', Chris@17: ]) Chris@17: ->save(); Chris@17: EntityViewDisplay::load('node.article.default') Chris@17: ->setComponent($this->fieldName, [ Chris@17: 'type' => 'entity_reference_label', Chris@17: ]) Chris@17: ->save(); Chris@17: Chris@17: // Create a user and then login. Chris@17: $this->adminUser = $this->drupalCreateUser(['create article content']); Chris@17: $this->drupalLogin($this->adminUser); Chris@17: Chris@17: // Retrieve the autocomplete url. Chris@17: $this->drupalGet('node/add/article'); Chris@17: $result = $this->xpath('//input[@name="' . $this->fieldName . '[0][target_id]"]'); Chris@17: $this->autocompleteUrl = $this->getAbsoluteUrl($result[0]->getAttribute('data-autocomplete-path')); Chris@17: } Chris@17: Chris@17: /** Chris@17: * Helper function for JSON formatted requests. Chris@17: * Chris@17: * @param string|\Drupal\Core\Url $path Chris@17: * Drupal path or URL to load into Mink controlled browser. Chris@17: * @param array $options Chris@17: * (optional) Options to be forwarded to the url generator. Chris@17: * @param string[] $headers Chris@17: * (optional) An array containing additional HTTP request headers. Chris@17: * Chris@17: * @return string[] Chris@17: * Array representing decoded JSON response. Chris@17: */ Chris@17: protected function drupalGetJson($path, array $options = [], array $headers = []) { Chris@17: $options = array_merge_recursive(['query' => ['_format' => 'json']], $options); Chris@17: return Json::decode($this->drupalGet($path, $options, $headers)); Chris@17: } Chris@17: Chris@17: /** Chris@17: * Tests that the autocomplete method returns the good number of results. Chris@17: * Chris@17: * @see \Drupal\taxonomy\Controller\TermAutocompleteController::autocomplete() Chris@17: */ Chris@17: public function testAutocompleteCountResults() { Chris@17: // Test that no matching term found. Chris@17: $data = $this->drupalGetJson( Chris@17: $this->autocompleteUrl, Chris@17: ['query' => ['q' => 'zzz']] Chris@17: ); Chris@17: $this->assertTrue(empty($data), 'Autocomplete returned no results'); Chris@17: Chris@17: // Test that only one matching term found, when only one matches. Chris@17: $data = $this->drupalGetJson( Chris@17: $this->autocompleteUrl, Chris@17: ['query' => ['q' => 'aaa 10']] Chris@17: ); Chris@17: $this->assertEqual(1, count($data), 'Autocomplete returned 1 result'); Chris@17: Chris@17: // Test the correct number of matches when multiple are partial matches. Chris@17: $data = $this->drupalGetJson( Chris@17: $this->autocompleteUrl, Chris@17: ['query' => ['q' => 'aaa 1']] Chris@17: ); Chris@17: $this->assertEqual(3, count($data), 'Autocomplete returned 3 results'); Chris@17: Chris@17: // Tests that only 10 results are returned, even if there are more than 10 Chris@17: // matches. Chris@17: $data = $this->drupalGetJson( Chris@17: $this->autocompleteUrl, Chris@17: ['query' => ['q' => 'aaa']] Chris@17: ); Chris@17: $this->assertEqual(10, count($data), 'Autocomplete returned only 10 results (for over 10 matches)'); Chris@17: } Chris@17: Chris@17: /** Chris@17: * Tests that the autocomplete method returns properly ordered results. Chris@17: * Chris@17: * @see \Drupal\taxonomy\Controller\TermAutocompleteController::autocomplete() Chris@17: */ Chris@17: public function testAutocompleteOrderedResults() { Chris@17: $expectedResults = [ Chris@17: 'aaa 10 bbb', Chris@17: 'aaa 11 bbb', Chris@17: 'aaa 12 bbb', Chris@17: 'aaa 20 bbb', Chris@17: 'aaa 30 bbb', Chris@17: 'aaa 40 bbb', Chris@17: 'aaa 50 bbb', Chris@17: 'aaa 70 bbb', Chris@17: 'bbb 60 aaa', Chris@17: ]; Chris@17: // Build $expected to match the autocomplete results. Chris@17: $expected = []; Chris@17: foreach ($expectedResults as $termName) { Chris@17: $expected[] = [ Chris@17: 'value' => $termName . ' (' . $this->termIds[$termName] . ')', Chris@17: 'label' => $termName, Chris@17: ]; Chris@17: } Chris@17: Chris@17: $data = $this->drupalGetJson( Chris@17: $this->autocompleteUrl, Chris@17: ['query' => ['q' => 'bbb']] Chris@17: ); Chris@17: Chris@17: $this->assertIdentical($expected, $data); Chris@17: } Chris@17: Chris@17: }