/[drupal]/drupal/modules/system/system.test
ViewVC logotype

Contents of /drupal/modules/system/system.test

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.90 - (show annotations) (download) (as text)
Fri Oct 23 00:45:51 2009 UTC (5 weeks, 1 day ago) by dries
Branch: MAIN
CVS Tags: DRUPAL-7-0-UNSTABLE-10, HEAD
Changes since 1.89: +3 -3 lines
File MIME type: text/x-php
- Patch #608478 by seutje, Bojhan: replace 'Powered by' icon with text.
1 <?php
2 // $Id: system.test,v 1.89 2009/10/18 11:34:44 dries Exp $
3
4 /**
5 * Helper class for module test cases.
6 */
7 class ModuleTestCase extends DrupalWebTestCase {
8 protected $admin_user;
9
10 function setUp() {
11 parent::setUp('system_test');
12
13 $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'administer site configuration'));
14 $this->drupalLogin($this->admin_user);
15 }
16
17 /**
18 * Assert there are tables that begin with the specified base table name.
19 *
20 * @param $base_table
21 * Beginning of table name to look for.
22 * @param $count
23 * (optional) Whether or not to assert that there are tables that match the
24 * specified base table. Defaults to TRUE.
25 */
26 function assertTableCount($base_table, $count = TRUE) {
27 $tables = db_find_tables(Database::getConnection()->prefixTables('{' . $base_table . '}') . '%');
28
29 if ($count) {
30 return $this->assertTrue($tables, t('Tables matching "@base_table" found.', array('@base_table' => $base_table)));
31 }
32 return $this->assertFalse($tables, t('Tables matching "@base_table" not found.', array('@base_table' => $base_table)));
33 }
34
35 /**
36 * Assert the list of modules are enabled or disabled.
37 *
38 * @param $modules
39 * Module list to check.
40 * @param $enabled
41 * Expected module state.
42 */
43 function assertModules(array $modules, $enabled) {
44 module_list(TRUE);
45 foreach ($modules as $module) {
46 if ($enabled) {
47 $message = 'Module "@module" is enabled.';
48 }
49 else {
50 $message = 'Module "@module" is not enabled.';
51 }
52 $this->assertEqual(module_exists($module), $enabled, t($message, array('@module' => $module)));
53 }
54 }
55
56 /**
57 * Verify a log entry was entered for a module's status change.
58 * Called in the same way of the expected original watchdog() execution.
59 *
60 * @param $type
61 * The category to which this message belongs.
62 * @param $message
63 * The message to store in the log. Keep $message translatable
64 * by not concatenating dynamic values into it! Variables in the
65 * message should be added by using placeholder strings alongside
66 * the variables argument to declare the value of the placeholders.
67 * See t() for documentation on how $message and $variables interact.
68 * @param $variables
69 * Array of variables to replace in the message on display or
70 * NULL if message is already translated or not possible to
71 * translate.
72 * @param $severity
73 * The severity of the message, as per RFC 3164.
74 * @param $link
75 * A link to associate with the message.
76 */
77 function assertLogMessage($type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = '') {
78 $count = db_select('watchdog', 'w')
79 ->condition('type', $type)
80 ->condition('message', $message)
81 ->condition('variables', serialize($variables))
82 ->condition('severity', $severity)
83 ->condition('link', $link)
84 ->countQuery()
85 ->execute()
86 ->fetchField();
87 $this->assertTrue($count > 0, t('watchdog table contains @count rows for @message', array('@count' => $count, '@message' => $message)));
88 }
89 }
90
91 /**
92 * Test module enabling/disabling functionality.
93 */
94 class EnableDisableTestCase extends ModuleTestCase {
95 public static function getInfo() {
96 return array(
97 'name' => 'Enable/disable modules',
98 'description' => 'Enable/disable core module and confirm table creation/deletion.',
99 'group' => 'Module',
100 );
101 }
102
103 /**
104 * Enable a module, check the database for related tables, disable module,
105 * check for related tables, uninstall module, check for related tables.
106 * Also check for invocation of the hook_module_action hook.
107 */
108 function testEnableDisable() {
109 // Enable aggregator, and check tables.
110 $this->assertModules(array('aggregator'), FALSE);
111 $this->assertTableCount('aggregator', FALSE);
112
113 // Install (and enable) aggregator module.
114 $edit = array();
115 $edit['modules[Core][aggregator][enable]'] = 'aggregator';
116 $edit['modules[Core][forum][enable]'] = 'forum';
117 $this->drupalPost('admin/config/modules', $edit, t('Save configuration'));
118 $this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
119
120 // Check that hook_modules_installed and hook_modules_enabled hooks were invoked and check tables.
121 $this->assertText(t('hook_modules_installed fired for aggregator'), t('hook_modules_installed fired.'));
122 $this->assertText(t('hook_modules_enabled fired for aggregator'), t('hook_modules_enabled fired.'));
123 $this->assertModules(array('aggregator'), TRUE);
124 $this->assertTableCount('aggregator', TRUE);
125 $this->assertLogMessage('system', "%module module enabled.", array('%module' => 'aggregator'), WATCHDOG_INFO);
126
127 // Disable aggregator, check tables, uninstall aggregator, check tables.
128 $edit = array();
129 $edit['modules[Core][aggregator][enable]'] = FALSE;
130 $this->drupalPost('admin/config/modules', $edit, t('Save configuration'));
131 $this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
132
133 // Check that hook_modules_disabled hook was invoked and check tables.
134 $this->assertText(t('hook_modules_disabled fired for aggregator'), t('hook_modules_disabled fired.'));
135 $this->assertModules(array('aggregator'), FALSE);
136 $this->assertTableCount('aggregator', TRUE);
137 $this->assertLogMessage('system', "%module module disabled.", array('%module' => 'aggregator'), WATCHDOG_INFO);
138
139 // Uninstall the module.
140 $edit = array();
141 $edit['uninstall[aggregator]'] = 'aggregator';
142 $this->drupalPost('admin/config/modules/uninstall', $edit, t('Uninstall'));
143
144 $this->drupalPost(NULL, NULL, t('Uninstall'));
145 $this->assertText(t('The selected modules have been uninstalled.'), t('Modules status has been updated.'));
146
147 // Check that hook_modules_uninstalled hook was invoked and check tables.
148 $this->assertText(t('hook_modules_uninstalled fired for aggregator'), t('hook_modules_uninstalled fired.'));
149 $this->assertModules(array('aggregator'), FALSE);
150 $this->assertTableCount('aggregator', FALSE);
151 $this->assertLogMessage('system', "%module module uninstalled.", array('%module' => 'aggregator'), WATCHDOG_INFO);
152
153 // Reinstall (and enable) aggregator module.
154 $edit = array();
155 $edit['modules[Core][aggregator][enable]'] = 'aggregator';
156 $this->drupalPost('admin/config/modules', $edit, t('Save configuration'));
157 $this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
158 }
159 }
160
161 /**
162 * Test module dependency functionality.
163 */
164 class ModuleDependencyTestCase extends ModuleTestCase {
165 public static function getInfo() {
166 return array(
167 'name' => 'Module dependencies',
168 'description' => 'Enable module without dependency enabled.',
169 'group' => 'Module',
170 );
171 }
172
173 /**
174 * Attempt to enable translation module without locale enabled.
175 */
176 function testEnableWithoutDependency() {
177 // Attempt to enable content translation without locale enabled.
178 $edit = array();
179 $edit['modules[Core][translation][enable]'] = 'translation';
180 $this->drupalPost('admin/config/modules', $edit, t('Save configuration'));
181 $this->assertText(t('Some required modules must be enabled'), t('Dependecy required.'));
182
183 $this->assertModules(array('translation', 'locale'), FALSE);
184
185 // Assert that the locale tables weren't enabled.
186 $this->assertTableCount('languages', FALSE);
187 $this->assertTableCount('locale', FALSE);
188
189 $this->drupalPost(NULL, NULL, t('Continue'));
190 $this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
191
192 $this->assertModules(array('translation', 'locale'), TRUE);
193
194 // Assert that the locale tables were enabled.
195 $this->assertTableCount('languages', TRUE);
196 $this->assertTableCount('locale', TRUE);
197 }
198 }
199
200 /**
201 * Test module dependency on specific versions.
202 */
203 class ModuleVersionTestCase extends ModuleTestCase {
204 public static function getInfo() {
205 return array(
206 'name' => 'Module versions',
207 'description' => 'Check module version dependencies.',
208 'group' => 'Module',
209 );
210 }
211
212 function setup() {
213 parent::setUp('module_test');
214 }
215
216 /**
217 * Test version dependencies.
218 */
219 function testModuleVersions() {
220 $dependencies = array(
221 // Alternating between being compatible and incompatible with 7.x-2.4-beta3.
222 // The first is always a compatible.
223 'common_test',
224 // Branch incompatibility.
225 'common_test (1.x)',
226 // Branch compatibility.
227 'common_test (2.x)',
228 // Another branch incompatibility.
229 'common_test (>2.x)',
230 // Another branch compatibility.
231 'common_test (<=2.x)',
232 // Another branch incompatibility.
233 'common_test (<2.x)',
234 // Another branch compatibility.
235 'common_test (>=2.x)',
236 // Nonsense, misses a dash. Incompatible with everything.
237 'common_test (=7.x2.x, >=2.4)',
238 // Core version is optional. Compatible.
239 'common_test (=7.x-2.x, >=2.4-alpha2)',
240 // Test !=, explicitly incompatible.
241 'common_test (=2.x, !=2.4-beta3)',
242 // Three operations. Compatible.
243 'common_test (=2.x, !=2.3, <2.5)',
244 // Testing extra version. Incompatible.
245 'common_test (<=2.4-beta2)',
246 // Testing extra version. Compatible.
247 'common_test (>2.4-beta2)',
248 // Testing extra version. Incompatible.
249 'common_test (>2.4-rc0)',
250 );
251 variable_set('dependencies', $dependencies);
252 $n = count($dependencies);
253 for ($i = 0; $i < $n; $i++) {
254 $this->drupalGet('admin/config/modules');
255 $checkbox = $this->xpath('//input[@id="edit-modules-testing-module-test-enable"]');
256 $this->assertEqual(!empty($checkbox[0]['disabled']), $i % 2, $dependencies[$i]);
257 }
258 }
259 }
260
261 /**
262 * Test required modules functionality.
263 */
264 class ModuleRequiredTestCase extends ModuleTestCase {
265 public static function getInfo() {
266 return array(
267 'name' => 'Required modules',
268 'description' => 'Attempt disabling of required modules.',
269 'group' => 'Module',
270 );
271 }
272
273 /**
274 * Assert that core required modules cannot be disabled.
275 */
276 function testDisableRequired() {
277 $required_modules = drupal_required_modules();
278 $this->drupalGet('admin/config/modules');
279 foreach ($required_modules as $module) {
280 // Check to make sure the checkbox for required module is not found.
281 $this->assertNoFieldByName('modules[Core][' . $module . '][enable]');
282 }
283 }
284 }
285
286 class IPAddressBlockingTestCase extends DrupalWebTestCase {
287 protected $blocking_user;
288
289 /**
290 * Implement getInfo().
291 */
292 public static function getInfo() {
293 return array(
294 'name' => 'IP address blocking',
295 'description' => 'Test IP address blocking.',
296 'group' => 'System'
297 );
298 }
299
300 /**
301 * Implement setUp().
302 */
303 function setUp() {
304 parent::setUp();
305
306 // Create user.
307 $this->blocking_user = $this->drupalCreateUser(array('block IP addresses'));
308 $this->drupalLogin($this->blocking_user);
309 }
310
311 /**
312 * Test a variety of user input to confirm correct validation and saving of data.
313 */
314 function testIPAddressValidation() {
315 $this->drupalGet('admin/config/people/ip-blocking');
316
317 // Block a valid IP address.
318 $edit = array();
319 $edit['ip'] = '192.168.1.1';
320 $this->drupalPost('admin/config/people/ip-blocking', $edit, t('Save'));
321 $ip = db_query("SELECT iid from {blocked_ips} WHERE ip = :ip", array(':ip' => $edit['ip']))->fetchField();
322 $this->assertNotNull($ip, t('IP address found in database'));
323 $this->assertRaw(t('The IP address %ip has been blocked.', array('%ip' => $edit['ip'])), t('IP address was blocked.'));
324
325 // Try to block an IP address that's already blocked.
326 $edit = array();
327 $edit['ip'] = '192.168.1.1';
328 $this->drupalPost('admin/config/people/ip-blocking', $edit, t('Save'));
329 $this->assertText(t('This IP address is already blocked.'));
330
331 // Try to block a reserved IP address.
332 $edit = array();
333 $edit['ip'] = '255.255.255.255';
334 $this->drupalPost('admin/config/people/ip-blocking', $edit, t('Save'));
335 $this->assertText(t('Please enter a valid IP address.'));
336
337 // Try to block a reserved IP address.
338 $edit = array();
339 $edit['ip'] = 'test.example.com';
340 $this->drupalPost('admin/config/people/ip-blocking', $edit, t('Save'));
341 $this->assertText(t('Please enter a valid IP address.'));
342
343 // Submit an empty form.
344 $edit = array();
345 $edit['ip'] = '';
346 $this->drupalPost('admin/config/people/ip-blocking', $edit, t('Save'));
347 $this->assertText(t('Please enter a valid IP address.'));
348
349 // Submit your own IP address. This fails, although it works when testing manually.
350 // TODO: on some systems this test fails due to a bug or inconsistency in cURL.
351 // $edit = array();
352 // $edit['ip'] = ip_address();
353 // $this->drupalPost('admin/config/people/ip-blocking', $edit, t('Save'));
354 // $this->assertText(t('You may not block your own IP address.'));
355 }
356 }
357
358 class CronRunTestCase extends DrupalWebTestCase {
359 /**
360 * Implement getInfo().
361 */
362 public static function getInfo() {
363 return array(
364 'name' => 'Cron run',
365 'description' => 'Test cron run.',
366 'group' => 'System'
367 );
368 }
369
370 /**
371 * Test cron runs.
372 */
373 function testCronRun() {
374 global $base_url;
375
376 // Run cron anonymously without any cron key.
377 $this->drupalGet($base_url . '/cron.php', array('external' => TRUE));
378 $this->assertResponse(403);
379
380 // Run cron anonymously with a random cron key.
381 $key = $this->randomName(16);
382 $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key)));
383 $this->assertResponse(403);
384
385 // Run cron anonymously with the valid cron key.
386 $key = variable_get('cron_key', 'drupal');
387 $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key)));
388 $this->assertResponse(200);
389 }
390
391 /**
392 * Follow every image paths in the previously retrieved content.
393 */
394 function drupalGetAllImages() {
395 foreach ($this->xpath('//img') as $image) {
396 $this->drupalGet($this->getAbsoluteUrl($image['src']));
397 }
398 }
399
400 /**
401 * Ensure that the cron image callback to run it automatically is working.
402 *
403 * In these tests we do not use REQUEST_TIME to track start time, because we
404 * need the exact time when cron is triggered.
405 */
406 function testCronThreshold() {
407 // Ensure cron does not run when the cron threshold is enabled and was
408 // not passed.
409 $start_cron_last = time();
410 variable_set('cron_last', $start_cron_last);
411 variable_set('cron_safe_threshold', 10);
412 $this->drupalGet('');
413 // Follow every image path on the page.
414 $this->drupalGetAllImages();
415 $this->assertTrue($start_cron_last == variable_get('cron_last', NULL), t('Cron does not run when the cron threshold is not passed.'));
416
417 // Test if cron runs when the cron threshold was passed.
418 $start_cron_last = time() - 15;
419 variable_set('cron_last', $start_cron_last);
420 $this->drupalGet('');
421 // Follow every image path on the page.
422 $this->drupalGetAllImages();
423 $this->assertTrue(variable_get('cron_last', NULL) > $start_cron_last, t('Cron runs when the cron threshold is passed.'));
424
425 // Test if cron does not run when the cron threshold was is disabled.
426 $start_cron_last = time() - 15;
427 variable_set('cron_safe_threshold', 0);
428 variable_set('cron_last', $start_cron_last);
429 $this->drupalGet('');
430 // Follow every image path on the page.
431 $this->drupalGetAllImages();
432 $this->assertTrue($start_cron_last == variable_get('cron_last', NULL), t('Cron does not run when the cron threshold is disabled.'));
433 }
434
435 /**
436 * Ensure that temporary files are removed.
437 *
438 * Create files for all the possible combinations of age and status. We are
439 * using UPDATE statments rather than file_save() because it would set the
440 * timestamp.
441 */
442 function testTempFileCleanup() {
443 // Temporary file that is older than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
444 $temp_old = file_save_data('');
445 db_update('file')
446 ->fields(array(
447 'status' => 0,
448 'timestamp' => 1,
449 ))
450 ->condition('fid', $temp_old->fid)
451 ->execute();
452 $this->assertTrue(file_exists($temp_old->uri), t('Old temp file was created correctly.'));
453
454 // Temporary file that is less than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
455 $temp_new = file_save_data('');
456 db_update('file')
457 ->fields(array('status' => 0))
458 ->condition('fid', $temp_new->fid)
459 ->execute();
460 $this->assertTrue(file_exists($temp_new->uri), t('New temp file was created correctly.'));
461
462 // Permanent file that is older than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
463 $perm_old = file_save_data('');
464 db_update('file')
465 ->fields(array('timestamp' => 1))
466 ->condition('fid', $temp_old->fid)
467 ->execute();
468 $this->assertTrue(file_exists($perm_old->uri), t('Old permanent file was created correctly.'));
469
470 // Permanent file that is newer than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
471 $perm_new = file_save_data('');
472 $this->assertTrue(file_exists($perm_new->uri), t('New permanent file was created correctly.'));
473
474 // Run cron and then ensure that only the old, temp file was deleted.
475 $this->cronRun();
476 $this->assertFalse(file_exists($temp_old->uri), t('Old temp file was correctly removed.'));
477 $this->assertTrue(file_exists($temp_new->uri), t('New temp file was correctly ignored.'));
478 $this->assertTrue(file_exists($perm_old->uri), t('Old permanent file was correctly ignored.'));
479 $this->assertTrue(file_exists($perm_new->uri), t('New permanent file was correctly ignored.'));
480 }
481 }
482
483 class AdminMetaTagTestCase extends DrupalWebTestCase {
484 /**
485 * Implement getInfo().
486 */
487 public static function getInfo() {
488 return array(
489 'name' => 'Fingerprinting meta tag',
490 'description' => 'Confirm that the fingerprinting meta tag appears as expected.',
491 'group' => 'System'
492 );
493 }
494
495 /**
496 * Verify that the meta tag HTML is generated correctly.
497 */
498 public function testMetaTag() {
499 list($version, ) = explode('.', VERSION);
500 $string = '<meta name="Generator" content="Drupal ' . $version . ' (http://drupal.org)" />';
501 $this->drupalGet('node');
502 $this->assertRaw($string, t('Fingerprinting meta tag generated correctly.'), t('System'));
503 }
504 }
505
506 /**
507 * Tests custom access denied functionality.
508 */
509 class AccessDeniedTestCase extends DrupalWebTestCase {
510 protected $admin_user;
511
512 public static function getInfo() {
513 return array(
514 'name' => '403 functionality',
515 'description' => 'Tests page access denied functionality, including custom 403 pages.',
516 'group' => 'System'
517 );
518 }
519
520 function setUp() {
521 parent::setUp();
522
523 // Create an administrative user.
524 $this->admin_user = $this->drupalCreateUser(array('administer site configuration', 'administer blocks'));
525 $this->drupalLogin($this->admin_user);
526 }
527
528 function testAccessDenied() {
529 $this->drupalGet('admin');
530 $this->assertText(t('Access denied'), t('Found the default 403 page'));
531
532 $edit = array(
533 'title' => array(FIELD_LANGUAGE_NONE => array(array('value' => $this->randomName(10)))),
534 'body' => array(FIELD_LANGUAGE_NONE => array(array('value' => $this->randomName(100)))),
535 );
536 $node = $this->drupalCreateNode($edit);
537
538 // Use a custom 403 page.
539 $this->drupalPost('admin/config/system/site-information', array('site_403' => 'node/' . $node->nid), t('Save configuration'));
540
541 $this->drupalGet('admin');
542 $this->assertText($node->title[FIELD_LANGUAGE_NONE][0]['value'], t('Found the custom 403 page'));
543
544 // Logout and check that the user login block is shown on custom 403 pages.
545 $this->drupalLogout();
546
547 $this->drupalGet('admin');
548 $this->assertText($node->title[FIELD_LANGUAGE_NONE][0]['value'], t('Found the custom 403 page'));
549 $this->assertText(t('User login'), t('Blocks are shown on the custom 403 page'));
550
551 // Log back in and remove the custom 403 page.
552 $this->drupalLogin($this->admin_user);
553 $this->drupalPost('admin/config/system/site-information', array('site_403' => ''), t('Save configuration'));
554
555 // Logout and check that the user login block is shown on default 403 pages.
556 $this->drupalLogout();
557
558 $this->drupalGet('admin');
559 $this->assertText(t('Access denied'), t('Found the default 403 page'));
560 $this->assertText(t('User login'), t('Blocks are shown on the default 403 page'));
561
562 // Log back in, set the custom 403 page to /user and remove the block
563 $this->drupalLogin($this->admin_user);
564 variable_set('site_403', 'user');
565 $this->drupalPost('admin/structure/block', array('user_login[region]' => '-1'), t('Save blocks'));
566
567 // Check that we can log in from the 403 page.
568 $this->drupalLogout();
569 $edit = array(
570 'name' => $this->admin_user->name,
571 'pass' => $this->admin_user->pass_raw,
572 );
573 $this->drupalPost('admin/config/system/site-information', $edit, t('Log in'));
574
575 // Check that we're still on the same page.
576 $this->assertText(t('Site information'));
577 }
578 }
579
580 class PageNotFoundTestCase extends DrupalWebTestCase {
581 protected $admin_user;
582
583 /**
584 * Implement getInfo().
585 */
586 public static function getInfo() {
587 return array(
588 'name' => '404 functionality',
589 'description' => "Tests page not found functionality, including custom 404 pages.",
590 'group' => 'System'
591 );
592 }
593
594 /**
595 * Implement setUp().
596 */
597 function setUp() {
598 parent::setUp();
599
600 // Create an administrative user.
601 $this->admin_user = $this->drupalCreateUser(array('administer site configuration'));
602 $this->drupalLogin($this->admin_user);
603 }
604
605 function testPageNotFound() {
606 $this->drupalGet($this->randomName(10));
607 $this->assertText(t('Page not found'), t('Found the default 404 page'));
608
609 $edit = array(
610 'title' => array(FIELD_LANGUAGE_NONE => array(array('value' => $this->randomName(10)))),
611 'body' => array(FIELD_LANGUAGE_NONE => array(array('value' => $this->randomName(100)))),
612 );
613 $node = $this->drupalCreateNode($edit);
614
615 // Use a custom 404 page.
616 $this->drupalPost('admin/config/system/site-information', array('site_404' => 'node/' . $node->nid), t('Save configuration'));
617
618 $this->drupalGet($this->randomName(10));
619 $this->assertText($node->title[FIELD_LANGUAGE_NONE][0]['value'], t('Found the custom 404 page'));
620 }
621 }
622
623 /**
624 * Tests site maintenance functionality.
625 */
626 class SiteMaintenanceTestCase extends DrupalWebTestCase {
627 protected $admin_user;
628
629 public static function getInfo() {
630 return array(
631 'name' => 'Site maintenance mode functionality',
632 'description' => 'Test access to site while in maintenance mode.',
633 'group' => 'System',
634 );
635 }
636
637 function setUp() {
638 parent::setUp();
639
640 // Create a user allowed to access site in maintenance mode.
641 $this->user = $this->drupalCreateUser(array('access site in maintenance mode'));
642 // Create an administrative user.
643 $this->admin_user = $this->drupalCreateUser(array('administer site configuration', 'access site in maintenance mode'));
644 $this->drupalLogin($this->admin_user);
645 }
646
647 /**
648 * Verify site maintenance mode functionality.
649 */
650 function testSiteMaintenance() {
651 // Turn on maintenance mode.
652 $edit = array(
653 'maintenance_mode' => 1,
654 );
655 $this->drupalPost('admin/config/development/maintenance', $edit, t('Save configuration'));
656
657 $admin_message = t('Operating in maintenance mode. <a href="@url">Go online.</a>', array('@url' => url('admin/config/development/maintenance')));
658 $user_message = t('Operating in maintenance mode.');
659 $offline_message = t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal')));
660
661 $this->drupalGet('');
662 $this->assertRaw($admin_message, t('Found the site maintenance mode message.'));
663
664 // Logout and verify that offline message is displayed.
665 $this->drupalLogout();
666 $this->drupalGet('');
667 $this->assertText($offline_message);
668 $this->drupalGet('node');
669 $this->assertText($offline_message);
670 $this->drupalGet('user/register');
671 $this->assertText($offline_message);
672 $this->drupalGet('user/password');
673 $this->assertText($offline_message);
674
675 // Verify that user is able to log in.
676 $this->drupalGet('user');
677 $this->assertNoText($offline_message);
678 $this->drupalGet('user/login');
679 $this->assertNoText($offline_message);
680
681 // Log in user and verify that maintenance mode message is displayed
682 // directly after login.
683 $edit = array(
684 'name' => $this->user->name,
685 'pass' => $this->user->pass_raw,
686 );
687 $this->drupalPost(NULL, $edit, t('Log in'));
688 $this->assertText($user_message);
689
690 // Log in administrative user and configure a custom site offline message.
691 $this->drupalLogout();
692 $this->drupalLogin($this->admin_user);
693 $this->drupalGet('admin/config/development/maintenance');
694 $this->assertNoRaw($admin_message, t('Site maintenance mode message not displayed.'));
695
696 $offline_message = 'Sorry, not online.';
697 $edit = array(
698 'maintenance_mode_message' => $offline_message,
699 );
700 $this->drupalPost(NULL, $edit, t('Save configuration'));
701
702 // Logout and verify that custom site offline message is displayed.
703 $this->drupalLogout();
704 $this->drupalGet('');
705 $this->assertRaw($offline_message, t('Found the site offline message.'));
706 }
707 }
708
709 /**
710 * Tests generic date and time handling capabilities of Drupal.
711 */
712 class DateTimeFunctionalTest extends DrupalWebTestCase {
713 public static function getInfo() {
714 return array(
715 'name' => 'Date and time',
716 'description' => 'Configure date and time settings. Test date formatting and time zone handling, including daylight saving time.',
717 'group' => 'System',
718 );
719 }
720
721 function setUp() {
722 parent::setUp();
723
724 // Create admin user and log in admin user.
725 $this->admin_user = $this->drupalCreateUser(array('administer site configuration'));
726 $this->drupalLogin($this->admin_user);
727 }
728
729
730 /**
731 * Test time zones and DST handling.
732 */
733 function testTimeZoneHandling() {
734 // Setup date/time settings for Honolulu time.
735 variable_set('date_default_timezone', 'Pacific/Honolulu');
736 variable_set('configurable_timezones', 0);
737 variable_set('date_format_medium', 'Y-m-d H:i:s O');
738
739 // Create some nodes with different authored-on dates.
740 $date1 = '2007-01-31 21:00:00 -1000';
741 $date2 = '2007-07-31 21:00:00 -1000';
742 $node1 = $this->drupalCreateNode(array('created' => strtotime($date1), 'type' => 'article'));
743 $node2 = $this->drupalCreateNode(array('created' => strtotime($date2), 'type' => 'article'));
744
745 // Confirm date format and time zone.
746 $this->drupalGet("node/$node1->nid");
747 $this->assertText('2007-01-31 21:00:00 -1000', t('Date should be identical, with GMT offset of -10 hours.'));
748 $this->drupalGet("node/$node2->nid");
749 $this->assertText('2007-07-31 21:00:00 -1000', t('Date should be identical, with GMT offset of -10 hours.'));
750
751 // Set time zone to Los Angeles time.
752 variable_set('date_default_timezone', 'America/Los_Angeles');
753
754 // Confirm date format and time zone.
755 $this->drupalGet("node/$node1->nid");
756 $this->assertText('2007-01-31 23:00:00 -0800', t('Date should be two hours ahead, with GMT offset of -8 hours.'));
757 $this->drupalGet("node/$node2->nid");
758 $this->assertText('2007-08-01 00:00:00 -0700', t('Date should be three hours ahead, with GMT offset of -7 hours.'));
759 }
760
761 /**
762 * Test date type configuration.
763 */
764 function testDateTypeConfiguration() {
765 // Confirm system date types appear.
766 $this->drupalGet('admin/config/regional/date-time');
767 $this->assertText(t('Medium'), 'System date types appear in date type list.');
768 $this->assertNoRaw('href="/admin/config/regional/date-time/types/medium/delete"', 'No delete link appear for system date types.');
769
770 // Add custom date type.
771 $this->clickLink(t('Add date type'));
772 $date_type = $this->randomName(8);
773 $machine_name = 'machine_' . $date_type;
774 $date_format = 'd.m.Y - H:i';
775 $edit = array(
776 'date_type' => $date_type,
777 'machine_name' => $machine_name,
778 'date_format' => $date_format,
779 );
780 $this->drupalPost('admin/config/regional/date-time/types/add', $edit, t('Add date type'));
781 $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time', array('absolute' => TRUE)), t('Correct page redirection.'));
782 $this->assertText(t('New date type added successfully.'), 'Date type added confirmation message appears.');
783 $this->assertText($date_type, 'Custom date type appears in the date type list.');
784 $this->assertText(t('delete'), 'Delete link for custom date type appears.');
785
786 // Delete custom date type.
787 $this->clickLink(t('delete'));
788 $this->drupalPost('admin/config/regional/date-time/types/' . $machine_name . '/delete', array(), t('Remove'));
789 $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time', array('absolute' => TRUE)), t('Correct page redirection.'));
790 $this->assertText(t('Removed date type ' . $date_type), 'Custom date type removed.');
791 }
792
793 /**
794 * Test date format configuration.
795 */
796 function testDateFormatConfiguration() {
797 // Confirm 'no custom date formats available' message appears.
798 $this->drupalGet('admin/config/regional/date-time/formats');
799 $this->assertText(t('No custom date formats available.'), 'No custom date formats message appears.');
800
801 // Add custom date format.
802 $this->clickLink(t('Add format'));
803 $edit = array(
804 'date_format' => 'Y',
805 );
806 $this->drupalPost('admin/config/regional/date-time/formats/add', $edit, t('Add format'));
807 $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time/formats', array('absolute' => TRUE)), t('Correct page redirection.'));
808 $this->assertNoText(t('No custom date formats available.'), 'No custom date formats message does not appear.');
809 $this->assertText(t('Custom date format added.'), 'Custom date format added.');
810
811 // Ensure custom date format appears in date type configuration options.
812 $this->drupalGet('admin/config/regional/date-time');
813 $this->assertRaw('<option value="Y">', 'Custom date format appears in options.');
814
815 // Edit custom date format.
816 $this->drupalGet('admin/config/regional/date-time/formats');
817 $this->clickLink(t('edit'));
818 $edit = array(
819 'date_format' => 'Y m',
820 );
821 $this->drupalPost($this->getUrl(), $edit, t('Save format'));
822 $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time/formats', array('absolute' => TRUE)), t('Correct page redirection.'));
823 $this->assertText(t('Custom date format updated.'), 'Custom date format successfully updated.');
824
825 // Delete custom date format.
826 $this->clickLink(t('delete'));
827 $this->drupalPost($this->getUrl(), array(), t('Remove'));
828 $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time/formats', array('absolute' => TRUE)), t('Correct page redirection.'));
829 $this->assertText(t('Removed date format'), 'Custom date format removed successfully.');
830 }
831 }
832
833 class PageTitleFiltering extends DrupalWebTestCase {
834 protected $content_user;
835 protected $saved_title;
836
837 /**
838 * Implement getInfo().
839 */
840 public static function getInfo() {
841 return array(
842 'name' => 'HTML in page titles',
843 'description' => 'Tests correct handling or conversion by drupal_set_title() and drupal_get_title().',
844 'group' => 'System'
845 );
846 }
847
848 /**
849 * Implement setUp().
850 */
851 function setUp() {
852 parent::setUp();
853
854 $this->content_user = $this->drupalCreateUser(array('create page content', 'access content'));
855 $this->drupalLogin($this->content_user);
856 $this->saved_title = drupal_get_title();
857 }
858
859 /**
860 * Reset page title.
861 */
862 function tearDown() {
863 // Restore the page title.
864 drupal_set_title($this->saved_title, PASS_THROUGH);
865
866 parent::tearDown();
867 }
868
869 /**
870 * Tests the handling of HTML by drupal_set_title() and drupal_get_title()
871 */
872 function testTitleTags() {
873 $title = "string with <em>HTML</em>";
874 // drupal_set_title's $filter is CHECK_PLAIN by default, so the title should be
875 // returned with check_plain().
876 drupal_set_title($title, CHECK_PLAIN);
877 $this->assertTrue(strpos(drupal_get_title(), '<em>') === FALSE, t('Tags in title converted to entities when $output is CHECK_PLAIN.'));
878 // drupal_set_title's $filter is passed as PASS_THROUGH, so the title should be
879 // returned with HTML.
880 drupal_set_title($title, PASS_THROUGH);
881 $this->assertTrue(strpos(drupal_get_title(), '<em>') !== FALSE, t('Tags in title are not converted to entities when $output is PASS_THROUGH.'));
882 // Generate node content.
883 $langcode = FIELD_LANGUAGE_NONE;
884 $edit = array(
885 "title[$langcode][0][value]" => '!SimpleTest! ' . $title . $this->randomName(20),
886 "body[$langcode][0][value]" => '!SimpleTest! test body' . $this->randomName(200),
887 );
888 // Create the node with HTML in the title.
889 $this->drupalPost('node/add/page', $edit, t('Save'));
890
891 $node = $this->drupalGetNodeByTitle($edit["title[$langcode][0][value]"]);
892 $this->assertNotNull($node, 'Node created and found in database');
893 $this->drupalGet("node/" . $node->nid);
894 $this->assertText(check_plain($edit["title[$langcode][0][value]"]), 'Check to make sure tags in the node title are converted.');
895 }
896 }
897
898 /**
899 * Test front page functionality and administration.
900 */
901 class FrontPageTestCase extends DrupalWebTestCase {
902
903 public static function getInfo() {
904 return array(
905 'name' => 'Front page',
906 'description' => 'Tests front page functionality and administration.',
907 'group' => 'System',
908 );
909 }
910
911 function setUp() {
912 parent::setUp('system_test');
913
914 // Create admin user, log in admin user, and create one node.
915 $this->admin_user = $this->drupalCreateUser(array('access content', 'administer site configuration'));
916 $this->drupalLogin($this->admin_user);
917 $this->node_path = "node/" . $this->drupalCreateNode(array('promote' => 1))->nid;
918
919 // Enable front page logging in system_test.module.
920 variable_set('front_page_output', 1);
921 }
922
923 /**
924 * Test front page functionality.
925 */
926 function testDrupalIsFrontPage() {
927 $this->drupalGet('');
928 $this->assertText(t('On front page.'), t('Path is the front page.'));
929 $this->drupalGet('node');
930 $this->assertText(t('On front page.'), t('Path is the front page.'));
931 $this->drupalGet($this->node_path);
932 $this->assertNoText(t('On front page.'), t('Path is not the front page.'));
933
934 // Change the front page to an invalid path.
935 $edit = array('site_frontpage' => 'kittens');
936 $this->drupalPost('admin/config/system/site-information', $edit, t('Save configuration'));
937 $this->assertText(t("The path '@path' is either invalid or you do not have access to it.", array('@path' => $edit['site_frontpage'])));
938
939 // Change the front page to a valid path.
940 $edit['site_frontpage'] = $this->node_path;
941 $this->drupalPost('admin/config/system/site-information', $edit, t('Save configuration'));
942 $this->assertText(t('The configuration options have been saved.'), t('The front page path has been saved.'));
943
944 $this->drupalGet('');
945 $this->assertText(t('On front page.'), t('Path is the front page.'));
946 $this->drupalGet('node');
947 $this->assertNoText(t('On front page.'), t('Path is not the front page.'));
948 $this->drupalGet($this->node_path);
949 $this->assertText(t('On front page.'), t('Path is the front page.'));
950 }
951 }
952
953 class SystemBlockTestCase extends DrupalWebTestCase {
954 public static function getInfo() {
955 return array(
956 'name' => 'Block functionality',
957 'description' => 'Configure and move powered-by block.',
958 'group' => 'System',
959 );
960 }
961
962 function setUp() {
963 parent::setUp();
964
965 // Create and login user
966 $admin_user = $this->drupalCreateUser(array('administer blocks'));
967 $this->drupalLogin($admin_user);
968 }
969
970 /**
971 * Test displaying and hiding the powered-by block.
972 */
973 function testPoweredByBlock() {
974 // Set block title and some settings to confirm that the interface is availble.
975 $this->drupalPost('admin/structure/block/manage/system/powered-by/configure', array('title' => $this->randomName(8)), t('Save block'));
976 $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
977
978 // Set the powered-by block to the footer region.
979 $edit = array();
980 $edit['system_powered-by[region]'] = 'footer';
981 $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
982 $this->assertText(t('The block settings have been updated.'), t('Block successfully moved to footer region.'));
983
984 // Confirm that the block is being displayed.
985 $this->drupalGet('node');
986 $this->assertRaw('id="block-system-powered-by"', t('Block successfully being displayed on the page.'));
987
988 // Set the block to the disabled region.
989 $edit = array();
990 $edit['system_powered-by[region]'] = '-1';
991 $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
992
993 // Confirm that the block is hidden.
994 $this->assertNoRaw('id="block-system-powered-by"', t('Block no longer appears on page.'));
995
996 // For convenience of developers, set the block to it's default settings.
997 $edit = array();
998 $edit['system_powered-by[region]'] = 'footer';
999 $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
1000 $this->drupalPost('admin/structure/block/manage/system/powered-by/configure', array('title' => ''), t('Save block'));
1001 }
1002 }
1003
1004 /**
1005 * Test main content rendering fallback provided by system module.
1006 */
1007 class SystemMainContentFallback extends DrupalWebTestCase {
1008 protected $admin_user;
1009 protected $web_user;
1010
1011 public static function getInfo() {
1012 return array(
1013 'name' => 'Main content rendering fallback',
1014 'description' => ' Test system module main content rendering fallback.',
1015 'group' => 'System',
1016 );
1017 }
1018
1019 function setUp() {
1020 parent::setUp('system_test');
1021
1022 // Create and login admin user.
1023 $this->admin_user = $this->drupalCreateUser(array(
1024 'access administration pages',
1025 'administer site configuration',
1026 'administer blocks',
1027 'administer nodes',
1028 ));
1029 $this->drupalLogin($this->admin_user);
1030
1031 // Create a web user.
1032 $this->web_user = $this->drupalCreateUser(array('access user profiles', 'access content'));
1033 }
1034
1035 /**
1036 * Test availability of main content.
1037 */
1038 function testMainContentFallback() {
1039 $edit = array();
1040 // Disable the dashboard module, which depends on the block module.
1041 $edit['modules[Core][dashboard][enable]'] = FALSE;
1042 $this->drupalPost('admin/config/modules', $edit, t('Save configuration'));
1043 $this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
1044 // Disable the block module.
1045 $edit['modules[Core][block][enable]'] = FALSE;
1046 $this->drupalPost('admin/config/modules', $edit, t('Save configuration'));
1047 $this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
1048 module_list(TRUE);
1049 $this->assertFalse(module_exists('block'), t('Block module disabled.'));
1050
1051 // At this point, no region is filled and fallback should be triggered.
1052 $this->drupalGet('admin/config/system/site-information');
1053 $this->assertField('site_name', t('Admin interface still availble.'));
1054
1055 // Fallback should not trigger when another module is handling content.
1056 $this->drupalGet('system-test/main-content-handling');
1057 $this->assertRaw('id="system-test-content"', t('Content handled by another module'));
1058 $this->assertText(t('Content to test main content fallback'), t('Main content still displayed.'));
1059
1060 // Fallback should trigger when another module
1061 // indicates that it is not handling the content.
1062 $this->drupalGet('system-test/main-content-fallback');
1063 $this->assertText(t('Content to test main content fallback'), t('Main content fallback properly triggers.'));
1064
1065 // Fallback should not trigger when another module is handling content.
1066 // Note that this test ensures that no duplicate
1067 // content gets created by the fallback.
1068 $this->drupalGet('system-test/main-content-duplication');
1069 $this->assertNoText(t('Content to test main content fallback'), t('Main content not duplicated.'));
1070
1071 // Request a user* page and see if it is displayed.
1072 $this->drupalLogin($this->web_user);
1073 $this->drupalGet('user/' . $this->web_user->uid . '/edit');
1074 $this->assertField('mail', t('User interface still availble.'));
1075
1076 // Enable the block module again.
1077 $this->drupalLogin($this->admin_user);
1078 $edit = array();
1079 $edit['modules[Core][block][enable]'] = 'block';
1080 $this->drupalPost('admin/config/modules', $edit, t('Save configuration'));
1081 $this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
1082 module_list(TRUE);
1083 $this->assertTrue(module_exists('block'), t('Block module re-enabled.'));
1084 }
1085 }
1086
1087 class SystemSettingsForm extends DrupalWebTestCase {
1088 /**
1089 * Implement getInfo().
1090 */
1091 public static function getInfo() {
1092 return array(
1093 'name' => 'System setting forms',
1094 'description' => 'Tests correctness of system_settings_form() processing.',
1095 'group' => 'System'
1096 );
1097 }
1098
1099 /**
1100 * Implement setUp().
1101 */
1102 function setUp() {
1103 parent::setUp();
1104
1105 variable_set('system_settings_form_test', TRUE);
1106 variable_set('system_settings_form_test_4', TRUE);
1107 }
1108
1109 /**
1110 * Reset page title.
1111 */
1112 function tearDown() {
1113 variable_del('system_settings_form_test');
1114 variable_del('system_settings_form_test_4');
1115
1116 parent::tearDown();
1117 }
1118
1119 /**
1120 * Tests the handling of automatic defaults in systems_settings_form().
1121 */
1122 function testAutomaticDefaults() {
1123 $form['system_settings_form_test'] = array(
1124 '#type' => 'checkbox',
1125 '#default_value' => FALSE,
1126 );
1127
1128 $form['system_settings_form_test_2'] = array(
1129 '#type' => 'checkbox',
1130 '#default_value' => FALSE,
1131 );
1132
1133 $form['system_settings_form_test_3'] = array(
1134 '#type' => 'checkbox',
1135 '#default_value' => TRUE,
1136 );
1137
1138 $form['has_children']['system_settings_form_test_4'] = array(
1139 '#type' => 'checkbox',
1140 '#default_value' => FALSE,
1141 );
1142
1143 $form['has_children']['system_settings_form_test_5'] = array(
1144 '#type' => 'checkbox',
1145 '#default_value' => TRUE,
1146 );
1147
1148 $automatic = system_settings_form($form, FALSE);
1149 $this->assertFalse($automatic['system_settings_form_test']['#default_value']);
1150 $this->assertFalse($automatic['system_settings_form_test_2']['#default_value']);
1151 $this->assertTrue($automatic['system_settings_form_test_3']['#default_value']);
1152 $this->assertFalse($automatic['has_children']['system_settings_form_test_4']['#default_value']);
1153 $this->assertTrue($automatic['has_children']['system_settings_form_test_5']['#default_value']);
1154
1155 $no_automatic = system_settings_form($form);
1156 $this->assertTrue($no_automatic['system_settings_form_test']['#default_value']);
1157 $this->assertFalse($no_automatic['system_settings_form_test_2']['#default_value']);
1158 $this->assertTrue($no_automatic['system_settings_form_test_3']['#default_value']);
1159 $this->assertTrue($no_automatic['has_children']['system_settings_form_test_4']['#default_value']);
1160 $this->assertTrue($no_automatic['has_children']['system_settings_form_test_5']['#default_value']);
1161 }
1162 }
1163
1164 /**
1165 * Tests for the theme interface functionality.
1166 */
1167 class SystemThemeFunctionalTest extends DrupalWebTestCase {
1168 public static function getInfo() {
1169 return array(
1170 'name' => 'Theme interface functionality',
1171 'description' => 'Tests the theme interface functionality by enabling and switching themes, and using an administration theme.',
1172 'group' => 'System',
1173 );
1174 }
1175
1176