synonyms_search.test 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. <?php
  2. /**
  3. * @file
  4. * Tests for the Synonyms Search module.
  5. */
  6. /**
  7. * Base class for tests of Synonyms Search module.
  8. */
  9. abstract class AbstractSearchSynonymsWebTestCase extends SynonymsWebTestCase {
  10. /**
  11. * What search type is being tested.
  12. *
  13. * @var string
  14. */
  15. protected $search_type = 'node';
  16. /**
  17. * Array of terms that will be used for testing.
  18. *
  19. * @var array
  20. */
  21. protected $terms = array();
  22. /**
  23. * SetUp method.
  24. */
  25. public function setUp($modules = array()) {
  26. $this->behavior_implementation['behavior'] = 'search';
  27. array_unshift($modules, 'synonyms_search');
  28. parent::setUp($modules);
  29. // Create a few terms and synonyms.
  30. $term = (object) array(
  31. 'vid' => $this->vocabulary->vid,
  32. 'name' => $this->randomName(),
  33. $this->fields['disabled']['field']['field_name'] => array(
  34. LANGUAGE_NONE => array(
  35. array('value' => $this->randomName()),
  36. ),
  37. ),
  38. );
  39. taxonomy_term_save($term);
  40. $this->terms['no_synonyms'] = $term;
  41. $term = (object) array(
  42. 'vid' => $this->vocabulary->vid,
  43. 'name' => $this->randomName(),
  44. $this->fields['enabled']['field']['field_name'] => array(
  45. LANGUAGE_NONE => array(
  46. array('value' => $this->randomName()),
  47. ),
  48. ),
  49. $this->fields['disabled']['field']['field_name'] => array(
  50. LANGUAGE_NONE => array(
  51. array('value' => $this->randomName()),
  52. ),
  53. ),
  54. );
  55. taxonomy_term_save($term);
  56. $this->terms['one_synonym'] = $term;
  57. $term = (object) array(
  58. 'vid' => $this->vocabulary->vid,
  59. 'name' => $this->randomName(),
  60. $this->fields['enabled']['field']['field_name'] => array(
  61. LANGUAGE_NONE => array(
  62. array('value' => $this->randomName()),
  63. array('value' => $this->randomName()),
  64. ),
  65. ),
  66. $this->fields['disabled']['field']['field_name'] => array(
  67. LANGUAGE_NONE => array(
  68. array('value' => $this->randomName()),
  69. ),
  70. ),
  71. );
  72. taxonomy_term_save($term);
  73. $this->terms['two_synonyms'] = $term;
  74. }
  75. /**
  76. * Retrieve search results.
  77. *
  78. * @param $keyword string
  79. * Keyword to supply to the search mechanism
  80. *
  81. * @return array
  82. * Array of HTML search results. Each element in this array is a single
  83. * search result represented in HTML code as Drupal search mechanism outputs
  84. * it
  85. */
  86. protected function getSearchResults($keyword) {
  87. $response = $this->drupalGet('search/' . $this->search_type . '/' . $keyword);
  88. $matches = array();
  89. preg_match_all('#\<li[^>]+class="search-result"[^>]*\>(.*?)\</li\>#si', $response, $matches);
  90. return $matches[1];
  91. }
  92. }
  93. /**
  94. * Test Synonyms module integration with Drupal search functionality for nodes.
  95. */
  96. class NodeSearchSynonymsWebTestCase extends AbstractSearchSynonymsWebTestCase {
  97. /**
  98. * GetInfo method.
  99. */
  100. public static function getInfo() {
  101. return array(
  102. 'name' => 'Synonyms node search integration',
  103. 'description' => 'Ensure that Synonyms module correctly integrates with the Drupal search functionality.',
  104. 'group' => 'Synonyms',
  105. );
  106. }
  107. /**
  108. * SetUp method.
  109. */
  110. public function setUp($modules = array()) {
  111. $modules[] = 'entityreference';
  112. parent::setUp($modules);
  113. // Creating a test content type.
  114. $this->drupalPost('admin/structure/types/add', array(
  115. 'name' => 'Synonyms Test Content',
  116. 'type' => 'synonyms_test_content',
  117. ), 'Save content type');
  118. }
  119. /**
  120. * Test searching nodes by a term synonym.
  121. *
  122. * Since logically term and its synonyms represent the same entity, the idea
  123. * is that searching by a term synonym should trigger all content referencing
  124. * that term to be included in search results. Additionally we test that when
  125. * a synonym is deleted/edited in a term, corresponding content is no longer
  126. * encountered when searched by ex-synonym.
  127. */
  128. public function testSearchTermSynonym() {
  129. // Attaching term reference field to the new content type.
  130. $field = array(
  131. 'type' => 'taxonomy_term_reference',
  132. 'field_name' => 'synonyms_term_enabled',
  133. 'cardinality' => FIELD_CARDINALITY_UNLIMITED,
  134. 'settings' => array(
  135. 'allowed_values' => array(
  136. array(
  137. 'vocabulary' => $this->vocabulary->machine_name,
  138. 'parent' => 0,
  139. ),
  140. ),
  141. ),
  142. );
  143. $field = field_create_field($field);
  144. $instance = array(
  145. 'field_name' => $field['field_name'],
  146. 'entity_type' => 'node',
  147. 'bundle' => 'synonyms_test_content',
  148. 'label' => 'Synonym Terms',
  149. );
  150. field_create_instance($instance);
  151. // Creating a node, which references all the terms we have.
  152. $node = (object) array(
  153. 'type' => 'synonyms_test_content',
  154. 'title' => $this->randomName(),
  155. 'synonyms_term_enabled' => array(LANGUAGE_NONE => array(
  156. array('tid' => $this->terms['no_synonyms']->tid),
  157. array('tid' => $this->terms['one_synonym']->tid),
  158. array('tid' => $this->terms['two_synonyms']->tid),
  159. )),
  160. );
  161. node_save($node);
  162. // Rebuilding Search index.
  163. $this->cronRun();
  164. foreach ($this->terms as $k => $term) {
  165. $this->assertSearchResults($term->name, array($node), 'Searching by name of the term ' . $k);
  166. $items = field_get_items('taxonomy_term', $term, $this->fields['disabled']['field']['field_name']);
  167. if (is_array($items)) {
  168. foreach ($items as $delta => $item) {
  169. $this->assertSearchResults($item['value'], array(), 'Searching by not enabled search integration field value #' . $delta . ' of term ' . $k);
  170. }
  171. }
  172. $items = field_get_items('taxonomy_term', $term, $this->fields['enabled']['field']['field_name']);
  173. if (is_array($items)) {
  174. foreach ($items as $delta => $item) {
  175. $this->assertSearchResults($item['value'], array($node), 'Searching by synonym #' . $delta . ' of the term ' . $k);
  176. }
  177. }
  178. }
  179. // Removing a synonym from the term. Then asserting node got re-indexed with
  180. // new values of synonyms.
  181. $deleted_synonym = array_pop($this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE]);
  182. taxonomy_term_save($this->terms['one_synonym']);
  183. $this->cronRun();
  184. $this->assertSearchResults($deleted_synonym['value'], array(), 'Searching by recently deleted synonym of a taxonomy term yields no results.');
  185. // Editing a synonym in a term. Then asserting node got re-indexed with new
  186. // values of synonyms.
  187. $ex_synonym = $this->terms['two_synonyms']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'];
  188. $this->terms['two_synonyms']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'] = $this->randomName();
  189. taxonomy_term_save($this->terms['two_synonyms']);
  190. $this->cronRun();
  191. $this->assertSearchResults($ex_synonym, array(), 'Searching by recently changed synonym of a taxonomy term yields no results.');
  192. // We disable entire field from search integration and make sure for all
  193. // synonyms search results are empty.
  194. synonyms_behavior_implementation_delete($this->behavior_implementation);
  195. $this->cronRun();
  196. foreach ($this->terms as $k => $term) {
  197. $items = field_get_items('taxonomy_term', $term, $this->fields['enabled']['field']['field_name']);
  198. if (is_array($items)) {
  199. foreach ($items as $synonym) {
  200. $this->assertSearchResults($synonym['value'], array(), 'Searching by ' . $k . ' term synonym, which field was recently disabled from search behavior yields no results.');
  201. }
  202. }
  203. }
  204. }
  205. /**
  206. * Test searching nodes by a term synonym when referenced by entity reference.
  207. *
  208. * This test pretty much does the same thing as the testSearchTermSynonym()
  209. * with the only different that the terms are referenced through entity
  210. * reference field type.
  211. */
  212. public function testSearchTermSynonymEntityReference() {
  213. // Attaching entity reference field to the new content type.
  214. $field = array(
  215. 'type' => 'entityreference',
  216. 'field_name' => 'synonyms_term_enabled',
  217. 'cardinality' => FIELD_CARDINALITY_UNLIMITED,
  218. 'settings' => array(
  219. 'target_type' => 'taxonomy_term',
  220. 'handler_settings' => array(
  221. 'target_bundles' => array($this->vocabulary->machine_name),
  222. ),
  223. ),
  224. );
  225. $field = field_create_field($field);
  226. $instance = array(
  227. 'field_name' => $field['field_name'],
  228. 'entity_type' => 'node',
  229. 'bundle' => 'synonyms_test_content',
  230. 'label' => 'Synonym Terms',
  231. );
  232. field_create_instance($instance);
  233. // Creating a node, which references all the terms we have.
  234. $node = (object) array(
  235. 'type' => 'synonyms_test_content',
  236. 'title' => $this->randomName(),
  237. 'synonyms_term_enabled' => array(LANGUAGE_NONE => array(
  238. array('target_id' => $this->terms['no_synonyms']->tid),
  239. array('target_id' => $this->terms['one_synonym']->tid),
  240. array('target_id' => $this->terms['two_synonyms']->tid),
  241. )),
  242. );
  243. node_save($node);
  244. // Rebuilding Search index.
  245. $this->cronRun();
  246. foreach ($this->terms as $k => $term) {
  247. $this->assertSearchResults($term->name, array($node), 'Searching by name of the term ' . $k);
  248. $items = field_get_items('taxonomy_term', $term, $this->fields['disabled']['field']['field_name']);
  249. if (is_array($items)) {
  250. foreach ($items as $delta => $item) {
  251. $this->assertSearchResults($item['value'], array(), 'Searching by not enabled search integration field value #' . $delta . ' of term ' . $k);
  252. }
  253. }
  254. $items = field_get_items('taxonomy_term', $term, $this->fields['enabled']['field']['field_name']);
  255. if (is_array($items)) {
  256. foreach ($items as $delta => $item) {
  257. $this->assertSearchResults($item['value'], array($node), 'Searching by synonym #' . $delta . ' of the term ' . $k);
  258. }
  259. }
  260. }
  261. // Removing a synonym from the term. Then asserting node got re-indexed with
  262. // new values of synonyms.
  263. $deleted_synonym = array_pop($this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE]);
  264. taxonomy_term_save($this->terms['one_synonym']);
  265. $this->cronRun();
  266. $this->assertSearchResults($deleted_synonym['value'], array(), 'Searching by recently deleted synonym of a taxonomy term yields no results.');
  267. // Editing a synonym in a term. Then asserting node got re-indexed with new
  268. // values of synonyms.
  269. $ex_synonym = $this->terms['two_synonyms']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'];
  270. $this->terms['two_synonyms']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'] = $this->randomName();
  271. taxonomy_term_save($this->terms['two_synonyms']);
  272. $this->cronRun();
  273. $this->assertSearchResults($ex_synonym, array(), 'Searching by recently changed synonym of a taxonomy term yields no results.');
  274. // We disable entire field from search integration and make sure for all
  275. // synonyms search results are empty.
  276. synonyms_behavior_implementation_delete($this->behavior_implementation);
  277. $this->cronRun();
  278. foreach ($this->terms as $k => $term) {
  279. $items = field_get_items('taxonomy_term', $term, $this->fields['enabled']['field']['field_name']);
  280. if (is_array($items)) {
  281. foreach ($items as $synonym) {
  282. $this->assertSearchResults($synonym['value'], array(), 'Searching by ' . $k . ' term synonym, which field was recently disabled from search behavior yields no results.');
  283. }
  284. }
  285. }
  286. }
  287. /**
  288. * Assert search results.
  289. *
  290. * @param $keyword string
  291. * Keyword to supply to the search mechanism
  292. * @param $results array
  293. * Array of fully loaded nodes that are expected to be on search results
  294. * @param $message string
  295. * Drupal assertion message to display on test results page
  296. */
  297. protected function assertSearchResults($keyword, $results, $message) {
  298. $matches = $this->getSearchResults($keyword);
  299. if (count($matches) != count($results)) {
  300. $this->fail($message);
  301. return;
  302. }
  303. $matches = implode('', $matches);
  304. foreach ($results as $node) {
  305. if (strpos($matches, 'node/' . $node->nid) === FALSE) {
  306. $this->fail($message);
  307. return;
  308. }
  309. }
  310. $this->pass($message);
  311. }
  312. }
  313. /**
  314. * Test Synonyms module integration with Drupal search for taxonomy terms.
  315. */
  316. class TermSearchSynonymsWebTestCase extends AbstractSearchSynonymsWebTestCase {
  317. protected $search_type = 'term';
  318. /**
  319. * GetInfo method.
  320. */
  321. public static function getInfo() {
  322. return array(
  323. 'name' => 'Synonyms term search integration',
  324. 'description' => 'Ensure that Synonyms module correctly integrates with the Term Search module.',
  325. 'group' => 'Synonyms',
  326. );
  327. }
  328. /**
  329. * SetUp method.
  330. */
  331. public function setUp($modules = array()) {
  332. $modules[] = 'term_search';
  333. parent::setUp($modules);
  334. $active_searches = variable_get('search_active_modules', array('node', 'user'));
  335. $active_searches[] = 'term_search';
  336. variable_set('search_active_modules', $active_searches);
  337. }
  338. /**
  339. * Test searching terms by their synonyms.
  340. */
  341. public function testSearchTermSynonym() {
  342. // Rebuilding Search index.
  343. $this->cronRun();
  344. foreach ($this->terms as $k => $term) {
  345. $this->assertSearchResults($term->name, array($term), 'Searching by name of the term ' . $k);
  346. $items = field_get_items('taxonomy_term', $term, $this->fields['disabled']['field']['field_name']);
  347. if (is_array($items)) {
  348. foreach ($items as $delta => $item) {
  349. $this->assertSearchResults($item['value'], array(), 'Searching by not enabled search integration field value #' . $delta . ' of term ' . $k);
  350. }
  351. }
  352. $items = field_get_items('taxonomy_term', $term, $this->fields['enabled']['field']['field_name']);
  353. if (is_array($items)) {
  354. foreach ($items as $delta => $item) {
  355. $this->assertSearchResults($item['value'], array($term), 'Searching by synonym #' . $delta . ' of the term ' . $k);
  356. }
  357. }
  358. }
  359. // Removing a synonym from the term. Then asserting it got re-indexed with
  360. // new values of synonyms.
  361. $deleted_synonym = array_pop($this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE]);
  362. taxonomy_term_save($this->terms['one_synonym']);
  363. $this->cronRun();
  364. $this->assertSearchResults($deleted_synonym['value'], array(), 'Searching by recently deleted synonym of a taxonomy term yields no results.');
  365. // Editing a synonym in a term. Then asserting it got re-indexed with new
  366. // values of synonyms.
  367. $ex_synonym = $this->terms['two_synonyms']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'];
  368. $this->terms['two_synonyms']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'] = $this->randomName();
  369. taxonomy_term_save($this->terms['two_synonyms']);
  370. $this->cronRun();
  371. $this->assertSearchResults($ex_synonym, array(), 'Searching by recently changed synonym of a taxonomy term yields no results.');
  372. // We disable entire field from search integration and make sure for all
  373. // synonyms search results are empty.
  374. synonyms_behavior_implementation_delete($this->behavior_implementation);
  375. $this->cronRun();
  376. foreach ($this->terms as $k => $term) {
  377. $items = field_get_items('taxonomy_term', $term, $this->fields['enabled']['field']['field_name']);
  378. if (is_array($items)) {
  379. foreach ($items as $synonym) {
  380. $this->assertSearchResults($synonym['value'], array(), 'Searching by ' . $k . ' term synonym, which field was recently disabled from search behavior yields no results.');
  381. }
  382. }
  383. }
  384. }
  385. /**
  386. * Assert search results.
  387. *
  388. * @param $keyword string
  389. * Keyword to supply to the search mechanism
  390. * @param $results array
  391. * Array of fully loaded terms that are expected to be on search results
  392. * @param $message string
  393. * Drupal assertion message to display on test results page
  394. */
  395. protected function assertSearchResults($keyword, $results, $message) {
  396. $matches = $this->getSearchResults($keyword);
  397. if (count($matches) != count($results)) {
  398. $this->fail($message);
  399. return;
  400. }
  401. $matches = implode('', $matches);
  402. foreach ($results as $term) {
  403. if (strpos($matches, 'taxonomy/term/' . $term->tid) === FALSE) {
  404. $this->fail($message);
  405. return;
  406. }
  407. }
  408. $this->pass($message);
  409. }
  410. }