base.test 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. <?php
  2. abstract class ViewsDataExportBaseTest extends ViewsTestCase {
  3. protected function setUp() {
  4. $modules = func_get_args();
  5. if (isset($modules[0]) && is_array($modules[0])) {
  6. $modules = $modules[0];
  7. }
  8. $modules[] = 'views_data_export';
  9. $modules[] = 'views_ui';
  10. $modules[] = 'views';
  11. parent::setUp($modules);
  12. // Define the schema and views data variable before enabling the test module.
  13. variable_set('views_test_schema', $this->schemaDefinition());
  14. variable_set('views_test_views_data', $this->viewsData());
  15. variable_set('views_test_views_plugins', $this->viewsPlugins());
  16. module_enable(array('views_test'));
  17. $this->resetAll();
  18. // Load the test dataset.
  19. $data_set = $this->dataSet();
  20. $query = db_insert('views_test')
  21. ->fields(array_keys($data_set[0]));
  22. foreach ($data_set as $record) {
  23. $query->values($record);
  24. }
  25. $query->execute();
  26. $this->checkPermissions(array(), TRUE);
  27. }
  28. /**
  29. * This function allows to enable views ui from a higher class which can't change the setup function anymore.
  30. *
  31. * @TODO
  32. * Convert existing setUp functions.
  33. */
  34. function enableViewsUi() {
  35. module_enable(array('views_ui'));
  36. // @TODO Figure out why it's required to clear the cache here.
  37. views_module_include('views_default', TRUE);
  38. views_get_all_views(TRUE);
  39. menu_rebuild();
  40. }
  41. /**
  42. * The schema definition.
  43. */
  44. protected function schemaDefinition() {
  45. $schema['views_test'] = array(
  46. 'description' => 'Basic test table for Views tests.',
  47. 'fields' => array(
  48. 'id' => array(
  49. 'type' => 'serial',
  50. 'unsigned' => TRUE,
  51. 'not null' => TRUE,
  52. ),
  53. 'name' => array(
  54. 'description' => "A person's name",
  55. 'type' => 'varchar',
  56. 'length' => 255,
  57. 'not null' => TRUE,
  58. 'default' => '',
  59. ),
  60. 'age' => array(
  61. 'description' => "The person's age",
  62. 'type' => 'int',
  63. 'unsigned' => TRUE,
  64. 'not null' => TRUE,
  65. 'default' => 0),
  66. 'job' => array(
  67. 'description' => "The person's job",
  68. 'type' => 'varchar',
  69. 'length' => 255,
  70. 'not null' => TRUE,
  71. 'default' => 'Undefined',
  72. ),
  73. 'created' => array(
  74. 'description' => "The creation date of this record",
  75. 'type' => 'int',
  76. 'unsigned' => TRUE,
  77. 'not null' => TRUE,
  78. 'default' => 0,
  79. ),
  80. ),
  81. 'primary key' => array('id'),
  82. 'unique keys' => array(
  83. 'name' => array('name')
  84. ),
  85. 'indexes' => array(
  86. 'ages' => array('age'),
  87. ),
  88. );
  89. return $schema;
  90. }
  91. /**
  92. * The views data definition.
  93. */
  94. protected function viewsData() {
  95. // Declaration of the base table.
  96. $data['views_test']['table'] = array(
  97. 'group' => t('Views test'),
  98. 'base' => array(
  99. 'field' => 'id',
  100. 'title' => t('Views test'),
  101. 'help' => t('Users who have created accounts on your site.'),
  102. ),
  103. );
  104. // Declaration of fields.
  105. $data['views_test']['id'] = array(
  106. 'title' => t('ID'),
  107. 'help' => t('The test data ID'),
  108. 'field' => array(
  109. 'handler' => 'views_handler_field_numeric',
  110. 'click sortable' => TRUE,
  111. ),
  112. 'argument' => array(
  113. 'handler' => 'views_handler_argument_numeric',
  114. ),
  115. 'filter' => array(
  116. 'handler' => 'views_handler_filter_numeric',
  117. ),
  118. 'sort' => array(
  119. 'handler' => 'views_handler_sort',
  120. ),
  121. );
  122. $data['views_test']['name'] = array(
  123. 'title' => t('Name'),
  124. 'help' => t('The name of the person'),
  125. 'field' => array(
  126. 'handler' => 'views_handler_field',
  127. 'click sortable' => TRUE,
  128. ),
  129. 'argument' => array(
  130. 'handler' => 'views_handler_argument_string',
  131. ),
  132. 'filter' => array(
  133. 'handler' => 'views_handler_filter_string',
  134. ),
  135. 'sort' => array(
  136. 'handler' => 'views_handler_sort',
  137. ),
  138. );
  139. $data['views_test']['age'] = array(
  140. 'title' => t('Age'),
  141. 'help' => t('The age of the person'),
  142. 'field' => array(
  143. 'handler' => 'views_handler_field_numeric',
  144. 'click sortable' => TRUE,
  145. ),
  146. 'argument' => array(
  147. 'handler' => 'views_handler_argument_numeric',
  148. ),
  149. 'filter' => array(
  150. 'handler' => 'views_handler_filter_numeric',
  151. ),
  152. 'sort' => array(
  153. 'handler' => 'views_handler_sort',
  154. ),
  155. );
  156. $data['views_test']['job'] = array(
  157. 'title' => t('Job'),
  158. 'help' => t('The job of the person'),
  159. 'field' => array(
  160. 'handler' => 'views_handler_field',
  161. 'click sortable' => TRUE,
  162. ),
  163. 'argument' => array(
  164. 'handler' => 'views_handler_argument_string',
  165. ),
  166. 'filter' => array(
  167. 'handler' => 'views_handler_filter_string',
  168. ),
  169. 'sort' => array(
  170. 'handler' => 'views_handler_sort',
  171. ),
  172. );
  173. $data['views_test']['created'] = array(
  174. 'title' => t('Created'),
  175. 'help' => t('The creation date of this record'),
  176. 'field' => array(
  177. 'handler' => 'views_handler_field_date',
  178. 'click sortable' => TRUE,
  179. ),
  180. 'argument' => array(
  181. 'handler' => 'views_handler_argument_date',
  182. ),
  183. 'filter' => array(
  184. 'handler' => 'views_handler_filter_date',
  185. ),
  186. 'sort' => array(
  187. 'handler' => 'views_handler_sort_date',
  188. ),
  189. );
  190. return $data;
  191. }
  192. protected function viewsPlugins() {
  193. return array();
  194. }
  195. /**
  196. * A very simple test dataset.
  197. */
  198. protected function dataSet() {
  199. return array(
  200. array(
  201. 'name' => 'John',
  202. 'age' => 25,
  203. 'job' => 'Singer',
  204. 'created' => gmmktime(0, 0, 0, 1, 1, 2000),
  205. ),
  206. array(
  207. 'name' => 'George',
  208. 'age' => 27,
  209. 'job' => 'Singer',
  210. 'created' => gmmktime(0, 0, 0, 1, 2, 2000),
  211. ),
  212. array(
  213. 'name' => 'Ringo',
  214. 'age' => 28,
  215. 'job' => 'Drummer',
  216. 'created' => gmmktime(6, 30, 30, 1, 1, 2000),
  217. ),
  218. array(
  219. 'name' => 'Paul',
  220. 'age' => 26,
  221. 'job' => 'Songwriter',
  222. 'created' => gmmktime(6, 0, 0, 1, 1, 2000),
  223. ),
  224. array(
  225. 'name' => 'Meredith',
  226. 'age' => 30,
  227. 'job' => 'Speaker',
  228. 'created' => gmmktime(6, 30, 10, 1, 1, 2000),
  229. ),
  230. );
  231. }
  232. /**
  233. * Build and return a basic view of the views_test table.
  234. *
  235. * @return view
  236. */
  237. protected function getBasicView() {
  238. views_include('view');
  239. // Create the basic view.
  240. $view = new view();
  241. $view->vid = 'test_view';
  242. $view->add_display('default');
  243. $view->base_table = 'views_test';
  244. // Set up the fields we need.
  245. $display = $view->new_display('default', 'Master', 'default');
  246. $display->override_option('fields', array(
  247. 'id' => array(
  248. 'id' => 'id',
  249. 'table' => 'views_test',
  250. 'field' => 'id',
  251. 'relationship' => 'none',
  252. ),
  253. 'name' => array(
  254. 'id' => 'name',
  255. 'table' => 'views_test',
  256. 'field' => 'name',
  257. 'relationship' => 'none',
  258. ),
  259. 'age' => array(
  260. 'id' => 'age',
  261. 'table' => 'views_test',
  262. 'field' => 'age',
  263. 'relationship' => 'none',
  264. ),
  265. ));
  266. // Set up the sort order.
  267. $display->override_option('sorts', array(
  268. 'id' => array(
  269. 'order' => 'ASC',
  270. 'id' => 'id',
  271. 'table' => 'views_test',
  272. 'field' => 'id',
  273. 'relationship' => 'none',
  274. ),
  275. ));
  276. // Set up the pager.
  277. $display->override_option('pager', array(
  278. 'type' => 'none',
  279. 'options' => array('offset' => 0),
  280. ));
  281. return $view;
  282. }
  283. public function logViewResult($result, $prefix = 'View result:<br>') {
  284. $this->verbose($prefix . '<br><pre>' . check_plain($result) .'</pre>');
  285. }
  286. public function assertBatchedExportEqual($path, $expected, $message) {
  287. $this->drupalGet($path);
  288. $output = $this->drupalGetContent();
  289. $this->logViewResult($output);
  290. $this->logViewResult($expected, 'Expected result:<br>');
  291. $this->assertEqual($this->normaliseString($output), $this->normaliseString($expected), $message);
  292. }
  293. public function assertExportEqual($a, $b, $message) {
  294. $this->logViewResult($a);
  295. $this->logViewResult($b, 'Expected result:<br>');
  296. $this->assertEqual($this->normaliseString($a), $this->normaliseString($b), $message);
  297. }
  298. protected function normaliseString($s) {
  299. // Normalize line endings
  300. // Convert all line-endings to UNIX format
  301. $s = str_replace("\r\n", "\n", $s);
  302. $s = str_replace("\r", "\n", $s);
  303. $s = trim($s);
  304. return $s;
  305. }
  306. }
  307. abstract class ViewsDataExportSimpleExportTest extends ViewsDataExportBaseTest {
  308. protected $vde_export_type;
  309. /**
  310. * Tests the non-batched export functionality for this style.
  311. */
  312. public function testNonBatchedExport() {
  313. $path = 'vde_test/' . $this->randomName();
  314. list($view, $expected) = $this->getExportView($path);
  315. // Save this view so we can hit the path.
  316. $view->save();
  317. // Ensure that the menu router system is rebuilt on the next page load.
  318. variable_set('menu_rebuild_needed', TRUE);
  319. $this->drupalGet($path);
  320. $result = $this->drupalGetContent();
  321. $this->assertExportEqual($result, $expected, 'Non batched ' . $this->vde_export_type . ' export matched expected output.');
  322. }
  323. /**
  324. * Tests the batched export functionality for this style.
  325. */
  326. public function testBatchedExport() {
  327. $path = 'vde_test/' . $this->randomName();
  328. list($view, $expected) = $this->getExportView($path);
  329. $display = &$view->display['vde_test']->handler;
  330. // Set this view to be batched.
  331. $display->override_option('use_batch', 'batch');
  332. // Save this view so we can hit the path.
  333. $view->save();
  334. // Ensure that the menu router system is rebuilt on the next page load.
  335. variable_set('menu_rebuild_needed', TRUE);
  336. $this->assertBatchedExportEqual($path, $expected, 'Batched ' . $this->vde_export_type . ' export matched expected output.');
  337. }
  338. /**
  339. * Get a very basic view and expected output for this style.
  340. *
  341. * @return
  342. * An array containing two elements:
  343. * - A View object, for the export.
  344. * - The expected out from that view, if is was executed without further
  345. * changes.
  346. */
  347. abstract protected function getExportView($path = 'vde_test');
  348. /**
  349. * Build and return a basic view of the views_test table.
  350. *
  351. * @return view
  352. */
  353. protected function getBasicExportView() {
  354. views_include('view');
  355. // Create the basic view.
  356. $view = new view();
  357. $view->vid = 'new';
  358. $view->base_table = 'views_test';
  359. // Set up the fields we need.
  360. $display = $view->new_display('default', 'Master', 'default');
  361. $display->override_option('fields', array(
  362. 'id' => array(
  363. 'id' => 'id',
  364. 'table' => 'views_test',
  365. 'field' => 'id',
  366. 'relationship' => 'none',
  367. ),
  368. 'name' => array(
  369. 'id' => 'name',
  370. 'table' => 'views_test',
  371. 'field' => 'name',
  372. 'relationship' => 'none',
  373. ),
  374. 'age' => array(
  375. 'id' => 'age',
  376. 'table' => 'views_test',
  377. 'field' => 'age',
  378. 'relationship' => 'none',
  379. ),
  380. ));
  381. // Set up the sort order.
  382. $display->override_option('sorts', array(
  383. 'id' => array(
  384. 'order' => 'ASC',
  385. 'id' => 'id',
  386. 'table' => 'views_test',
  387. 'field' => 'id',
  388. 'relationship' => 'none',
  389. ),
  390. ));
  391. // Set up the pager.
  392. $display->override_option('pager', array(
  393. 'type' => 'none',
  394. 'options' => array('offset' => 0),
  395. ));
  396. return $view;
  397. }
  398. /**
  399. * Get a view that's our basic view, but with hide if empty/0 support.
  400. *
  401. * We add this to the 'age' field.
  402. */
  403. protected function getHideIfEmptyExportView() {
  404. $view = $this->getBasicExportView();
  405. $display = $view->display['default']->handler;
  406. $display->override_option('fields', array(
  407. 'id' => array(
  408. 'id' => 'id',
  409. 'table' => 'views_test',
  410. 'field' => 'id',
  411. 'relationship' => 'none',
  412. ),
  413. 'name' => array(
  414. 'id' => 'name',
  415. 'table' => 'views_test',
  416. 'field' => 'name',
  417. 'relationship' => 'none',
  418. // Hide their name if its empty.
  419. 'hide_empty' => TRUE,
  420. // But we don't hide it if it's: 0.
  421. 'empty_zero' => FALSE,
  422. ),
  423. 'age' => array(
  424. 'id' => 'age',
  425. 'table' => 'views_test',
  426. 'field' => 'age',
  427. 'relationship' => 'none',
  428. // Hide their age if it's empty.
  429. 'hide_empty' => TRUE,
  430. 'empty_zero' => TRUE,
  431. ),
  432. ));
  433. return $view;
  434. }
  435. /**
  436. * Execute a given view very simply.
  437. *
  438. * This will take a view, and add a display plugin of the correct export type,
  439. * and then run it and compare it with the expected output.
  440. */
  441. protected function executeAndCompareGivenView(view $view, $expected, $message = '', $style_options = array()) {
  442. $path = 'vde_test/' . $this->randomName();
  443. $display = $view->new_display('views_data_export', 'Data export', 'vde_test');
  444. $display->override_option('style_plugin', $this->getStylePluginName());
  445. $display->override_option('style_options', $style_options);
  446. $display->override_option('path', $path);
  447. // Save this view so we can hit the path.
  448. $view->save();
  449. // Ensure that the menu router system is rebuilt on the next page load.
  450. variable_set('menu_rebuild_needed', TRUE);
  451. $this->drupalGet($path);
  452. $result = $this->drupalGetContent();
  453. $this->assertExportEqual($result, $expected, $message);
  454. }
  455. /**
  456. * Return the name of the style plugin represented by this test.
  457. */
  458. abstract protected function getStylePluginName();
  459. }