sbo__relationship_widgetTest.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. <?php
  2. namespace Tests\tripal_chado\fields;
  3. use StatonLab\TripalTestSuite\DBTransaction;
  4. use StatonLab\TripalTestSuite\TripalTestCase;
  5. module_load_include('php', 'tripal_chado', '../tests/TripalFieldTestHelper');
  6. class sbo__relationship_widgetTest extends TripalTestCase {
  7. // Uncomment to auto start and rollback db transactions per test method.
  8. use DBTransaction;
  9. /**
  10. * Data Provider: provides entities matching important test cases.
  11. *
  12. * Specifically, we will cover three relationship tables, which represent
  13. * the diversity in the chado schema v1.3:
  14. * organism_relationship: subject_id, type_id, object_id,
  15. * stock_relationship: subject_id, type_id, object_id, value, rank,
  16. * project_relationship: subject_project_id, type_id, object_project_id, rank
  17. *
  18. * @returns
  19. * Returns an array where each item to be tested has the paramaters
  20. * needed for initializeWidgetClass(). Specfically, $bundle_name,
  21. * $field_name, $widget_name, $entity_id.
  22. */
  23. public function provideEntities() {
  24. $data = [];
  25. foreach (['organism', 'stock', 'project'] as $base_table) {
  26. $field_name = 'sbo__relationship';
  27. $widget_name = 'sbo__relationship_widget';
  28. // Find a bundle which stores it's data in the given base table.
  29. // This will work on Travis since Tripal creates matching bundles by default.
  30. $bundle_details = db_query("
  31. SELECT bundle_id, type_column, type_id
  32. FROM chado_bundle b
  33. WHERE data_table=:table AND type_linker_table=''
  34. ORDER BY bundle_id ASC LIMIT 1",
  35. array(':table' => $base_table))->fetchObject();
  36. if (isset($bundle_details->bundle_id)) {
  37. $bundle_id = $bundle_details->bundle_id;
  38. }
  39. else {
  40. continue;
  41. }
  42. $bundle_name = 'bio_data_'.$bundle_id;
  43. // Create some entities so that we know there are some available to find.
  44. if ($bundle_details->type_column == 'type_id') {
  45. factory('chado.'. $base_table, 2)->create(['type_id' => $bundle_details->type_id]);
  46. }
  47. else {
  48. factory('chado.'. $base_table, 2)->create();
  49. }
  50. // Then publish them so we have entities.
  51. $this->publish($base_table);
  52. // Find an entity from the above bundle.
  53. // @todo find a way to create a fake entity for use here.
  54. $entity_id = db_query('SELECT id FROM tripal_entity WHERE bundle=:bundle LIMIT 1',
  55. array(':bundle' => $bundle_name))->fetchField();
  56. // set variables to guide testing.
  57. $expect = [
  58. 'has_rank' => TRUE,
  59. 'has_value' => FALSE,
  60. 'subject_key' => 'subject_id',
  61. 'object_key' => 'object_id',
  62. 'base_table' => $base_table,
  63. 'relationship_table' => $base_table.'_relationship'
  64. ];
  65. if ($base_table == 'organism') { $expect['has_rank'] = FALSE; }
  66. if ($base_table == 'stock') { $expect['has_value'] = TRUE; }
  67. if ($base_table == 'project') {
  68. $expect['subject_key'] = 'subject_project_id';
  69. $expect['object_key'] = 'object_project_id';
  70. }
  71. $data[] = [$bundle_name, $field_name, $widget_name, $entity_id, $expect];
  72. }
  73. return $data;
  74. }
  75. /**
  76. * Test that we can initialize the widget properly.
  77. *
  78. * @dataProvider provideEntities()
  79. *
  80. * @group widget
  81. * @group sbo__relationship
  82. */
  83. public function testWidgetClassInitialization($bundle_name, $field_name, $widget_name, $entity_id, $expect) {
  84. // Load the entity.
  85. $entity = entity_load('TripalEntity', [$entity_id]);
  86. $entity = $entity[$entity_id];
  87. // Initialize the widget class via the TripalFieldTestHelper class.
  88. $machine_names = array(
  89. 'field_name' => $field_name,
  90. 'widget_name' => $widget_name,
  91. );
  92. $field_info = field_info_field($field_name);
  93. $instance_info = field_info_instance('TripalEntity', $field_name, $bundle_name);
  94. $helper = new \TripalFieldTestHelper($bundle_name, $machine_names, $entity, $field_info, $instance_info);
  95. $widget_class = $helper->getInitializedClass();
  96. // Check we have the variables we initialized.
  97. $this->assertNotEmpty($helper->bundle,
  98. "Could not load the bundle.");
  99. $this->assertNotEmpty($helper->getFieldInfo($field_name),
  100. "Could not lookup the field information.");
  101. $this->assertNotEmpty($helper->getInstanceInfo($bundle_name, $field_name),
  102. "Could not lookup the instance information.");
  103. $this->assertNotEmpty($widget_class,
  104. "Couldn't create a widget class instance.");
  105. $this->assertNotEmpty($entity,
  106. "Couldn't load an entity.");
  107. // Check a little deeper...
  108. $this->assertEquals($helper->instance_info['settings']['chado_table'], $expect['relationship_table'],
  109. "Instance settings were not initialized fully.");
  110. }
  111. /**
  112. * Test the widget Form.
  113. *
  114. * @dataProvider provideEntities()
  115. *
  116. * @group widget
  117. * @group sbo__relationship
  118. */
  119. public function testWidgetForm($bundle_name, $field_name, $widget_name, $entity_id, $expect) {
  120. // Load the entity.
  121. $entity = entity_load('TripalEntity', [$entity_id]);
  122. $entity = $entity[$entity_id];
  123. // Initialize the widget class via the TripalFieldTestHelper class.
  124. $machine_names = array(
  125. 'field_name' => $field_name,
  126. 'widget_name' => $widget_name,
  127. );
  128. $field_info = field_info_field($field_name);
  129. $instance_info = field_info_instance('TripalEntity', $field_name, $bundle_name);
  130. $helper = new \TripalFieldTestHelper($bundle_name, $machine_names, $entity, $field_info, $instance_info);
  131. $widget_class = $helper->getInitializedClass();
  132. $base_table = $entity->chado_table;
  133. // Stub out a fake objects.
  134. $delta = 1;
  135. $langcode = LANGUAGE_NONE;
  136. $widget = $helper->mockElement($delta, $langcode);
  137. $form = $helper->mockForm($delta, $langcode);
  138. $form_state = $helper->mockFormState($delta, $langcode);
  139. $element = $helper->mockElement($delta, $langcode);
  140. $items = [
  141. 'value' => '',
  142. 'chado-'.$base_table.'_relationship__organism_relationship_id' => '',
  143. 'chado-'.$base_table.'_relationship__subject_id' => '',
  144. 'chado-'.$base_table.'_relationship__object_id' => '',
  145. 'chado-'.$base_table.'_relationship__type_id' => '',
  146. 'object_name' => '',
  147. 'subject_name' => '',
  148. 'type_name' => '',
  149. ];
  150. // Execute the form method.
  151. $widget_class->form($widget, $form, $form_state, $langcode, $items, $delta, $element);
  152. // Check the resulting for array
  153. $this->assertArrayHasKey('subject_name', $widget,
  154. "The form for $bundle_name($base_table) does not have a subject element.");
  155. $this->assertArrayHasKey('type_name', $widget,
  156. "The form for $bundle_name($base_table) does not have a type element.");
  157. $this->assertArrayHasKey('object_name', $widget,
  158. "The form for $bundle_name($base_table) does not have a object element.");
  159. // Check the subject/object keys were correctly determined.
  160. $this->assertEquals($expect['subject_key'], $widget['#subject_id_key'],
  161. "The form didn't determine the subject key correctly.");
  162. $this->assertEquals($expect['object_key'], $widget['#object_id_key'],
  163. "The form didn't determine the object key correctly.");
  164. }
  165. /**
  166. * DataProvider: Provides datasets to validate.
  167. */
  168. public function provideThings2Validate() {
  169. $data = [];
  170. foreach (['organism', 'stock', 'project'] as $base_table) {
  171. $base_table = $base_table;
  172. $field_name = 'sbo__relationship';
  173. $widget_name = 'sbo__relationship_widget';
  174. // Find a bundle which stores it's data in the given base table.
  175. // This will work on Travis since Tripal creates matching bundles by default.
  176. $bundle_details = db_query("
  177. SELECT bundle_id, type_column, type_id
  178. FROM chado_bundle b
  179. WHERE data_table=:table AND type_linker_table=''
  180. ORDER BY bundle_id ASC LIMIT 1",
  181. array(':table' => $base_table))->fetchObject();
  182. if (isset($bundle_details->bundle_id)) {
  183. $bundle_id = $bundle_details->bundle_id;
  184. }
  185. else {
  186. continue;
  187. }
  188. $bundle_name = 'bio_data_'.$bundle_id;
  189. // set variables to guide testing.
  190. $expect = [
  191. 'has_rank' => TRUE,
  192. 'has_value' => FALSE,
  193. 'subject_key' => 'subject_id',
  194. 'object_key' => 'object_id',
  195. 'base_table' => $base_table,
  196. 'relationship_table' => $base_table.'_relationship',
  197. ];
  198. if ($base_table == 'organism') { $expect['has_rank'] = FALSE; }
  199. if ($base_table == 'stock') { $expect['has_value'] = TRUE; }
  200. if ($base_table == 'project') {
  201. $expect['subject_key'] = 'subject_project_id';
  202. $expect['object_key'] = 'object_project_id';
  203. }
  204. // Create 5 fake records and publish them.
  205. if ($bundle_details->type_column == 'type_id') {
  206. factory('chado.'. $base_table, 5)->create(['type_id' => $bundle_details->type_id]);
  207. }
  208. else {
  209. factory('chado.'. $base_table, 5)->create();
  210. }
  211. // Then publish them so we have entities.
  212. $this->publish($base_table);
  213. $cvterm = factory('chado.cvterm')->create();
  214. // Find an entity from the above bundle.
  215. $ids = db_query('SELECT id FROM {tripal_entity} WHERE bundle=:bundle LIMIT 2',
  216. array(':bundle' => $bundle_name))->fetchCol();
  217. $entities = entity_load('TripalEntity', $ids);
  218. $entity = array_pop($entities);
  219. $entity2 = array_pop($entities);
  220. // Now Build our test cases for this base table.
  221. foreach (['user_create', 'existing', 'no_subject', 'no_object', 'no_type'] as $case) {
  222. $expect['test_case'] = $case;
  223. // First assume "existing" (later we will modify based on case).
  224. $values = [
  225. 'subject_name' => $entity2->chado_record->name,
  226. 'type_name' => $cvterm->name,
  227. 'vocabulary' => $cvterm->cv_id,
  228. 'object_name' => $entity->chado_record->name,
  229. // Both the form and load set the chado values
  230. // so we will set them here as well.
  231. 'chado-'.$base_table.'_relationship__'.$expect['subject_key'] => $entity2->chado_record->{$base_table.'_id'},
  232. 'chado-'.$base_table.'_relationship__type_id' => $cvterm->cvterm_id,
  233. 'chado-'.$base_table.'_relationship__'.$expect['object_key'] => $entity->chado_record->{$base_table.'_id'},
  234. ];
  235. if ($base_table == 'organism') {
  236. $values['subject_name'] = $entity2->chado_record->species;
  237. $values['object_name'] = $entity->chado_record->species;
  238. }
  239. $expect['num_errors'] = 0;
  240. // Now modify based on the case.
  241. switch ($case) {
  242. case 'user_create':
  243. $values[ 'chado-'.$base_table.'_relationship__'.$expect['subject_key'] ] = NULL;
  244. $values[ 'chado-'.$base_table.'_relationship__type_id' ] = NULL;
  245. $values[ 'chado-'.$base_table.'_relationship__'.$expect['object_key'] ] = NULL;
  246. break;
  247. case 'no_subject':
  248. $values['subject_name'] = '';
  249. $values[ 'chado-'.$base_table.'_relationship__'.$expect['subject_key'] ] = NULL;
  250. $expect['num_errors'] = 1;
  251. break;
  252. case 'no_object':
  253. $values['object_name'] = '';
  254. $values[ 'chado-'.$base_table.'_relationship__'.$expect['object_key'] ] = NULL;
  255. $expect['num_errors'] = 1;
  256. break;
  257. case 'no_type':
  258. $values['type_name'] = '';
  259. $values['vocabulary'] = NULL;
  260. $values[ 'chado-'.$base_table.'_relationship__type_id' ] = NULL;
  261. $expect['num_errors'] = 1;
  262. break;
  263. }
  264. $data[] = [
  265. [
  266. 'field_name' => $field_name,
  267. 'widget_name' => $widget_name,
  268. 'bundle_id' => $bundle_id,
  269. 'bundle_name' => $bundle_name,
  270. ],
  271. $entity,
  272. $values,
  273. $expect,
  274. ];
  275. }
  276. }
  277. return $data;
  278. }
  279. /**
  280. * Test sbo__relationship_widget->validate().
  281. *
  282. * @dataProvider provideThings2Validate()
  283. *
  284. * @group lacey-wip
  285. * @group widget
  286. * @group sbo__relationship
  287. */
  288. public function testWidgetValidate($info, $entity, $initial_values, $expect) {
  289. $base_table = $entity->chado_table;
  290. // Initialize the widget class via the TripalFieldTestHelper class.
  291. $machine_names = array(
  292. 'field_name' => $info['field_name'],
  293. 'widget_name' => $info['widget_name'],
  294. );
  295. $field_info = field_info_field($info['field_name']);
  296. $instance_info = field_info_instance('TripalEntity', $info['field_name'], $info['bundle_name']);
  297. $helper = new \TripalFieldTestHelper($info['bundle_name'], $machine_names, $entity, $field_info, $instance_info);
  298. $widget_class = $helper->getInitializedClass();
  299. // Mock objects.
  300. $field_name = $info['field_name'];
  301. $delta = 1;
  302. $langcode = LANGUAGE_NONE;
  303. $widget = $helper->mockElement($delta, $langcode);
  304. $form = $helper->mockForm($delta, $langcode);
  305. $form_state = $helper->mockFormState($delta, $langcode, $initial_values);
  306. $element = $helper->mockElement($delta, $langcode);
  307. $widget_class->validate($element, $form, $form_state, $langcode, $delta);
  308. // @debug print_r($form_state['values'][$field_name][$langcode][$delta]);
  309. // Ensure the chado-table__column entries are there.
  310. $this->assertArrayHasKey(
  311. 'chado-'.$base_table.'_relationship__'.$expect['subject_key'],
  312. $form_state['values'][$field_name][$langcode][$delta],
  313. 'Failed to find the subject_id in the processed values (Base: '.$base_table.'). This implies the validate function was not able to validate the subject.'
  314. );
  315. $this->assertArrayHasKey(
  316. 'chado-'.$base_table.'_relationship__'.$expect['object_key'],
  317. $form_state['values'][$field_name][$langcode][$delta],
  318. 'Failed to find the object_id in the processed values (Base: '.$base_table.'). This implies the validate function was not able to validate the object.'
  319. );
  320. $this->assertArrayHasKey(
  321. 'chado-'.$base_table.'_relationship__type_id',
  322. $form_state['values'][$field_name][$langcode][$delta],
  323. 'Failed to find the type_id in the processed values (Base: '.$base_table.'). This implies the validate function was not able to validate the type.'
  324. );
  325. // Check for errors.
  326. $errors = form_get_errors();
  327. // @debug print "Errors: " . print_r($errors, TRUE)."\n";
  328. if ($expect['num_errors'] === 0) {
  329. $this->assertEmpty($errors,
  330. "There should be no form errors for the following initial values: ".print_r($initial_values,TRUE)." But these were registered: ".print_r($errors, TRUE));
  331. }
  332. else {
  333. $this->assertEquals($expect['num_errors'], sizeof($errors),
  334. "The number of errors didn't match what we expected for the following initial values: ".print_r($initial_values,TRUE)." Here are the errors: ".print_r($errors, TRUE));
  335. }
  336. // Clean up after ourselves by removing any errors we logged.
  337. form_clear_error();
  338. }
  339. }