views_query.test 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. <?php
  2. /**
  3. * @file
  4. * Tests for Views query features.
  5. */
  6. /**
  7. * Abstract class for views testing.
  8. */
  9. abstract class ViewsTestCase extends DrupalWebTestCase {
  10. /**
  11. * Helper function: verify a result set returned by view.
  12. *
  13. * The comparison is done on the string representation of the columns of the
  14. * column map, taking the order of the rows into account, but not the order
  15. * of the columns.
  16. *
  17. * @param $view
  18. * An executed View.
  19. * @param $expected_result
  20. * An expected result set.
  21. * @param $column_map
  22. * An associative array mapping the columns of the result set from the view
  23. * (as keys) and the expected result set (as values).
  24. */
  25. protected function assertIdenticalResultset($view, $expected_result, $column_map = array(), $message = 'Identical result set') {
  26. return $this->assertIdenticalResultsetHelper($view, $expected_result, $column_map, $message, 'assertIdentical');
  27. }
  28. /**
  29. * Helper function: verify a result set returned by view..
  30. *
  31. * Inverse of ViewsTestCase::assertIdenticalResultset().
  32. *
  33. * @param $view
  34. * An executed View.
  35. * @param $expected_result
  36. * An expected result set.
  37. * @param $column_map
  38. * An associative array mapping the columns of the result set from the view
  39. * (as keys) and the expected result set (as values).
  40. */
  41. protected function assertNotIdenticalResultset($view, $expected_result, $column_map = array(), $message = 'Identical result set') {
  42. return $this->assertIdenticalResultsetHelper($view, $expected_result, $column_map, $message, 'assertNotIdentical');
  43. }
  44. protected function assertIdenticalResultsetHelper($view, $expected_result, $column_map, $message, $assert_method) {
  45. // Convert $view->result to an array of arrays.
  46. $result = array();
  47. foreach ($view->result as $key => $value) {
  48. $row = array();
  49. foreach ($column_map as $view_column => $expected_column) {
  50. // The comparison will be done on the string representation of the value.
  51. $row[$expected_column] = (string) $value->$view_column;
  52. }
  53. $result[$key] = $row;
  54. }
  55. // Remove the columns we don't need from the expected result.
  56. foreach ($expected_result as $key => $value) {
  57. $row = array();
  58. foreach ($column_map as $expected_column) {
  59. // The comparison will be done on the string representation of the value.
  60. $row[$expected_column] = (string) (is_object($value) ? $value->$expected_column : $value[$expected_column]);
  61. }
  62. $expected_result[$key] = $row;
  63. }
  64. // Reset the numbering of the arrays.
  65. $result = array_values($result);
  66. $expected_result = array_values($expected_result);
  67. $this->verbose('<pre>Returned data set: ' . print_r($result, TRUE) . "\n\nExpected: ". print_r($expected_result, TRUE));
  68. // Do the actual comparison.
  69. return $this->$assert_method($result, $expected_result, $message);
  70. }
  71. /**
  72. * Helper function: order an array of array based on a column.
  73. */
  74. protected function orderResultSet($result_set, $column, $reverse = FALSE) {
  75. $this->sort_column = $column;
  76. $this->sort_order = $reverse ? -1 : 1;
  77. usort($result_set, array($this, 'helperCompareFunction'));
  78. return $result_set;
  79. }
  80. protected $sort_column = NULL;
  81. protected $sort_order = 1;
  82. /**
  83. * Helper comparison function for orderResultSet().
  84. */
  85. protected function helperCompareFunction($a, $b) {
  86. $value1 = $a[$this->sort_column];
  87. $value2 = $b[$this->sort_column];
  88. if ($value1 == $value2) {
  89. return 0;
  90. }
  91. return $this->sort_order * (($value1 < $value2) ? -1 : 1);
  92. }
  93. /**
  94. * Helper function to check whether a button with a certain id exists and has a certain label.
  95. */
  96. protected function helperButtonHasLabel($id, $expected_label, $message = 'Label has the expected value: %label.') {
  97. return $this->assertFieldById($id, $expected_label, t($message, array('%label' => $expected_label)));
  98. }
  99. /**
  100. * Helper function to execute a view with debugging.
  101. *
  102. * @param view $view
  103. * @param array $args
  104. */
  105. protected function executeView($view, $args = array()) {
  106. $view->set_display();
  107. $view->pre_execute($args);
  108. $view->execute();
  109. $this->verbose('<pre>Executed view: ' . ((string) $view->build_info['query']) . '</pre>');
  110. }
  111. }
  112. abstract class ViewsSqlTest extends ViewsTestCase {
  113. protected function setUp() {
  114. parent::setUp('views', 'views_ui');
  115. // Define the schema and views data variable before enabling the test module.
  116. variable_set('views_test_schema', $this->schemaDefinition());
  117. variable_set('views_test_views_data', $this->viewsData());
  118. variable_set('views_test_views_plugins', $this->viewsPlugins());
  119. module_enable(array('views_test'));
  120. $this->resetAll();
  121. // Load the test dataset.
  122. $data_set = $this->dataSet();
  123. $query = db_insert('views_test')
  124. ->fields(array_keys($data_set[0]));
  125. foreach ($data_set as $record) {
  126. $query->values($record);
  127. }
  128. $query->execute();
  129. $this->checkPermissions(array(), TRUE);
  130. }
  131. /**
  132. * This function allows to enable views ui from a higher class which can't change the setup function anymore.
  133. *
  134. * @TODO
  135. * Convert existing setUp functions.
  136. */
  137. function enableViewsUi() {
  138. module_enable(array('views_ui'));
  139. // @TODO Figure out why it's required to clear the cache here.
  140. views_module_include('views_default', TRUE);
  141. views_get_all_views(TRUE);
  142. menu_rebuild();
  143. }
  144. /**
  145. * The schema definition.
  146. */
  147. protected function schemaDefinition() {
  148. $schema['views_test'] = array(
  149. 'description' => 'Basic test table for Views tests.',
  150. 'fields' => array(
  151. 'id' => array(
  152. 'type' => 'serial',
  153. 'unsigned' => TRUE,
  154. 'not null' => TRUE,
  155. ),
  156. 'name' => array(
  157. 'description' => "A person's name",
  158. 'type' => 'varchar',
  159. 'length' => 255,
  160. 'not null' => TRUE,
  161. 'default' => '',
  162. ),
  163. 'age' => array(
  164. 'description' => "The person's age",
  165. 'type' => 'int',
  166. 'unsigned' => TRUE,
  167. 'not null' => TRUE,
  168. 'default' => 0),
  169. 'job' => array(
  170. 'description' => "The person's job",
  171. 'type' => 'varchar',
  172. 'length' => 255,
  173. 'not null' => TRUE,
  174. 'default' => 'Undefined',
  175. ),
  176. 'created' => array(
  177. 'description' => "The creation date of this record",
  178. 'type' => 'int',
  179. 'unsigned' => TRUE,
  180. 'not null' => TRUE,
  181. 'default' => 0,
  182. ),
  183. ),
  184. 'primary key' => array('id'),
  185. 'unique keys' => array(
  186. 'name' => array('name')
  187. ),
  188. 'indexes' => array(
  189. 'ages' => array('age'),
  190. ),
  191. );
  192. return $schema;
  193. }
  194. /**
  195. * The views data definition.
  196. */
  197. protected function viewsData() {
  198. // Declaration of the base table.
  199. $data['views_test']['table'] = array(
  200. 'group' => t('Views test'),
  201. 'base' => array(
  202. 'field' => 'id',
  203. 'title' => t('Views test'),
  204. 'help' => t('Users who have created accounts on your site.'),
  205. ),
  206. );
  207. // Declaration of fields.
  208. $data['views_test']['id'] = array(
  209. 'title' => t('ID'),
  210. 'help' => t('The test data ID'),
  211. 'field' => array(
  212. 'handler' => 'views_handler_field_numeric',
  213. 'click sortable' => TRUE,
  214. ),
  215. 'argument' => array(
  216. 'handler' => 'views_handler_argument_numeric',
  217. ),
  218. 'filter' => array(
  219. 'handler' => 'views_handler_filter_numeric',
  220. ),
  221. 'sort' => array(
  222. 'handler' => 'views_handler_sort',
  223. ),
  224. );
  225. $data['views_test']['name'] = array(
  226. 'title' => t('Name'),
  227. 'help' => t('The name of the person'),
  228. 'field' => array(
  229. 'handler' => 'views_handler_field',
  230. 'click sortable' => TRUE,
  231. ),
  232. 'argument' => array(
  233. 'handler' => 'views_handler_argument_string',
  234. ),
  235. 'filter' => array(
  236. 'handler' => 'views_handler_filter_string',
  237. ),
  238. 'sort' => array(
  239. 'handler' => 'views_handler_sort',
  240. ),
  241. );
  242. $data['views_test']['age'] = array(
  243. 'title' => t('Age'),
  244. 'help' => t('The age of the person'),
  245. 'field' => array(
  246. 'handler' => 'views_handler_field_numeric',
  247. 'click sortable' => TRUE,
  248. ),
  249. 'argument' => array(
  250. 'handler' => 'views_handler_argument_numeric',
  251. ),
  252. 'filter' => array(
  253. 'handler' => 'views_handler_filter_numeric',
  254. ),
  255. 'sort' => array(
  256. 'handler' => 'views_handler_sort',
  257. ),
  258. );
  259. $data['views_test']['job'] = array(
  260. 'title' => t('Job'),
  261. 'help' => t('The job of the person'),
  262. 'field' => array(
  263. 'handler' => 'views_handler_field',
  264. 'click sortable' => TRUE,
  265. ),
  266. 'argument' => array(
  267. 'handler' => 'views_handler_argument_string',
  268. ),
  269. 'filter' => array(
  270. 'handler' => 'views_handler_filter_string',
  271. ),
  272. 'sort' => array(
  273. 'handler' => 'views_handler_sort',
  274. ),
  275. );
  276. $data['views_test']['created'] = array(
  277. 'title' => t('Created'),
  278. 'help' => t('The creation date of this record'),
  279. 'field' => array(
  280. 'handler' => 'views_handler_field_date',
  281. 'click sortable' => TRUE,
  282. ),
  283. 'argument' => array(
  284. 'handler' => 'views_handler_argument_date',
  285. ),
  286. 'filter' => array(
  287. 'handler' => 'views_handler_filter_date',
  288. ),
  289. 'sort' => array(
  290. 'handler' => 'views_handler_sort_date',
  291. ),
  292. );
  293. return $data;
  294. }
  295. protected function viewsPlugins() {
  296. return array();
  297. }
  298. /**
  299. * A very simple test dataset.
  300. */
  301. protected function dataSet() {
  302. return array(
  303. array(
  304. 'name' => 'John',
  305. 'age' => 25,
  306. 'job' => 'Singer',
  307. 'created' => gmmktime(0, 0, 0, 1, 1, 2000),
  308. ),
  309. array(
  310. 'name' => 'George',
  311. 'age' => 27,
  312. 'job' => 'Singer',
  313. 'created' => gmmktime(0, 0, 0, 1, 2, 2000),
  314. ),
  315. array(
  316. 'name' => 'Ringo',
  317. 'age' => 28,
  318. 'job' => 'Drummer',
  319. 'created' => gmmktime(6, 30, 30, 1, 1, 2000),
  320. ),
  321. array(
  322. 'name' => 'Paul',
  323. 'age' => 26,
  324. 'job' => 'Songwriter',
  325. 'created' => gmmktime(6, 0, 0, 1, 1, 2000),
  326. ),
  327. array(
  328. 'name' => 'Meredith',
  329. 'age' => 30,
  330. 'job' => 'Speaker',
  331. 'created' => gmmktime(6, 30, 10, 1, 1, 2000),
  332. ),
  333. );
  334. }
  335. /**
  336. * Build and return a basic view of the views_test table.
  337. *
  338. * @return view
  339. */
  340. protected function getBasicView() {
  341. views_include('view');
  342. // Create the basic view.
  343. $view = new view();
  344. $view->name = 'test_view';
  345. $view->add_display('default');
  346. $view->base_table = 'views_test';
  347. // Set up the fields we need.
  348. $display = $view->new_display('default', 'Master', 'default');
  349. $display->override_option('fields', array(
  350. 'id' => array(
  351. 'id' => 'id',
  352. 'table' => 'views_test',
  353. 'field' => 'id',
  354. 'relationship' => 'none',
  355. ),
  356. 'name' => array(
  357. 'id' => 'name',
  358. 'table' => 'views_test',
  359. 'field' => 'name',
  360. 'relationship' => 'none',
  361. ),
  362. 'age' => array(
  363. 'id' => 'age',
  364. 'table' => 'views_test',
  365. 'field' => 'age',
  366. 'relationship' => 'none',
  367. ),
  368. ));
  369. // Set up the sort order.
  370. $display->override_option('sorts', array(
  371. 'id' => array(
  372. 'order' => 'ASC',
  373. 'id' => 'id',
  374. 'table' => 'views_test',
  375. 'field' => 'id',
  376. 'relationship' => 'none',
  377. ),
  378. ));
  379. // Set up the pager.
  380. $display->override_option('pager', array(
  381. 'type' => 'none',
  382. 'options' => array('offset' => 0),
  383. ));
  384. return $view;
  385. }
  386. /**
  387. * Build and return a Page view of the views_test table.
  388. *
  389. * @return view
  390. */
  391. protected function getBasicPageView() {
  392. views_include('view');
  393. $view = $this->getBasicView();
  394. // In order to test exposed filters, we have to disable
  395. // the exposed forms cache.
  396. drupal_static_reset('views_exposed_form_cache');
  397. $display = $view->new_display('page', 'Page', 'page_1');
  398. return $view;
  399. }
  400. }