views_query.test 13 KB

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