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