summaryrefslogtreecommitdiff
path: root/modules/simpletest/tests
diff options
context:
space:
mode:
Diffstat (limited to 'modules/simpletest/tests')
-rw-r--r--modules/simpletest/tests/actions_loop_test.module1
-rw-r--r--modules/simpletest/tests/ajax.test72
-rw-r--r--modules/simpletest/tests/ajax_forms_test.module12
-rw-r--r--modules/simpletest/tests/ajax_test.module8
-rw-r--r--modules/simpletest/tests/cache.test34
-rw-r--r--modules/simpletest/tests/common.test65
-rw-r--r--modules/simpletest/tests/database_test.install1
-rw-r--r--modules/simpletest/tests/database_test.test34
-rw-r--r--modules/simpletest/tests/entity_query.test21
-rw-r--r--modules/simpletest/tests/error.test2
-rw-r--r--modules/simpletest/tests/file.test13
-rw-r--r--modules/simpletest/tests/form.test76
-rw-r--r--modules/simpletest/tests/form_test.module76
-rw-r--r--modules/simpletest/tests/image.test41
-rw-r--r--modules/simpletest/tests/menu.test94
-rw-r--r--modules/simpletest/tests/menu_test.module36
-rw-r--r--modules/simpletest/tests/pager.test159
-rw-r--r--modules/simpletest/tests/path.test46
-rw-r--r--modules/simpletest/tests/path_test.info6
-rw-r--r--modules/simpletest/tests/path_test.module23
-rw-r--r--modules/simpletest/tests/session.test11
-rw-r--r--modules/simpletest/tests/theme.test35
-rw-r--r--modules/simpletest/tests/theme_test.inc15
-rw-r--r--modules/simpletest/tests/theme_test.module18
-rw-r--r--modules/simpletest/tests/themes/test_theme/template.php6
-rw-r--r--modules/simpletest/tests/upgrade/drupal-6.trigger.database.php82
-rw-r--r--modules/simpletest/tests/upgrade/drupal-6.upload.database.php25
-rw-r--r--modules/simpletest/tests/upgrade/drupal-7.field.database.php16
-rw-r--r--modules/simpletest/tests/upgrade/drupal-7.trigger.database.php28
-rw-r--r--modules/simpletest/tests/upgrade/update.field.test61
-rw-r--r--modules/simpletest/tests/upgrade/update.trigger.test37
-rw-r--r--modules/simpletest/tests/upgrade/update.user.test35
-rw-r--r--modules/simpletest/tests/upgrade/upgrade.test8
-rw-r--r--modules/simpletest/tests/upgrade/upgrade.trigger.test39
-rw-r--r--modules/simpletest/tests/upgrade/upgrade.upload.test6
35 files changed, 1186 insertions, 56 deletions
diff --git a/modules/simpletest/tests/actions_loop_test.module b/modules/simpletest/tests/actions_loop_test.module
index 77764907b..261cb8008 100644
--- a/modules/simpletest/tests/actions_loop_test.module
+++ b/modules/simpletest/tests/actions_loop_test.module
@@ -81,6 +81,7 @@ function watchdog_skip_semaphore($type, $message, $variables = array(), $severit
'severity' => $severity,
'link' => $link,
'user' => $user,
+ 'uid' => isset($user->uid) ? $user->uid : 0,
'request_uri' => $base_root . request_uri(),
'referer' => $_SERVER['HTTP_REFERER'],
'ip' => ip_address(),
diff --git a/modules/simpletest/tests/ajax.test b/modules/simpletest/tests/ajax.test
index 9a76b9692..014a35042 100644
--- a/modules/simpletest/tests/ajax.test
+++ b/modules/simpletest/tests/ajax.test
@@ -127,6 +127,18 @@ class AJAXFrameworkTestCase extends AJAXTestCase {
'css' => drupal_get_path('module', 'system') . '/system.admin.css',
'js' => drupal_get_path('module', 'system') . '/system.js',
);
+ // @todo D8: Add a drupal_css_defaults() helper function.
+ $expected_css_html = drupal_get_css(array($expected['css'] => array(
+ 'type' => 'file',
+ 'group' => CSS_DEFAULT,
+ 'weight' => 0,
+ 'every_page' => FALSE,
+ 'media' => 'all',
+ 'preprocess' => TRUE,
+ 'data' => $expected['css'],
+ 'browsers' => array('IE' => TRUE, '!IE' => TRUE),
+ )), TRUE);
+ $expected_js_html = drupal_get_js('header', array($expected['js'] => drupal_js_defaults($expected['js'])), TRUE);
// Get the base page.
$this->drupalGet('ajax_forms_test_lazy_load_form');
@@ -135,13 +147,34 @@ class AJAXFrameworkTestCase extends AJAXTestCase {
$original_js = $original_settings['ajaxPageState']['js'];
// Verify that the base page doesn't have the settings and files that are to
- // be lazy loaded as part of the next request.
+ // be lazy loaded as part of the next requests.
$this->assertTrue(!isset($original_settings[$expected['setting_name']]), t('Page originally lacks the %setting, as expected.', array('%setting' => $expected['setting_name'])));
$this->assertTrue(!isset($original_settings[$expected['css']]), t('Page originally lacks the %css file, as expected.', array('%css' => $expected['css'])));
$this->assertTrue(!isset($original_settings[$expected['js']]), t('Page originally lacks the %js file, as expected.', array('%js' => $expected['js'])));
- // Submit the AJAX request.
- $commands = $this->drupalPostAJAX(NULL, array(), array('op' => t('Submit')));
+ // Submit the AJAX request without triggering files getting added.
+ $commands = $this->drupalPostAJAX(NULL, array('add_files' => FALSE), array('op' => t('Submit')));
+ $new_settings = $this->drupalGetSettings();
+
+ // Verify the setting was not added when not expected.
+ $this->assertTrue(!isset($new_settings['setting_name']), t('Page still lacks the %setting, as expected.', array('%setting' => $expected['setting_name'])));
+ // Verify a settings command does not add CSS or scripts to Drupal.settings
+ // and no command inserts the corresponding tags on the page.
+ $found_settings_command = FALSE;
+ $found_markup_command = FALSE;
+ foreach ($commands as $command) {
+ if ($command['command'] == 'settings' && (array_key_exists('css', $command['settings']['ajaxPageState']) || array_key_exists('js', $command['settings']['ajaxPageState']))) {
+ $found_settings_command = TRUE;
+ }
+ if (isset($command['data']) && ($command['data'] == $expected_js_html || $command['data'] == $expected_css_html)) {
+ $found_markup_command = TRUE;
+ }
+ }
+ $this->assertFalse($found_settings_command, t('Page state still lacks the %css and %js files, as expected.', array('%css' => $expected['css'], '%js' => $expected['js'])));
+ $this->assertFalse($found_markup_command, t('Page still lacks the %css and %js files, as expected.', array('%css' => $expected['css'], '%js' => $expected['js'])));
+
+ // Submit the AJAX request and trigger adding files.
+ $commands = $this->drupalPostAJAX(NULL, array('add_files' => TRUE), array('op' => t('Submit')));
$new_settings = $this->drupalGetSettings();
$new_css = $new_settings['ajaxPageState']['css'];
$new_js = $new_settings['ajaxPageState']['js'];
@@ -151,17 +184,6 @@ class AJAXFrameworkTestCase extends AJAXTestCase {
// Verify the expected CSS file was added, both to Drupal.settings, and as
// an AJAX command for inclusion into the HTML.
- // @todo A drupal_css_defaults() function in Drupal 8 would be nice.
- $expected_css_html = drupal_get_css(array($expected['css'] => array(
- 'type' => 'file',
- 'group' => CSS_DEFAULT,
- 'weight' => 0,
- 'every_page' => FALSE,
- 'media' => 'all',
- 'preprocess' => TRUE,
- 'data' => $expected['css'],
- 'browsers' => array('IE' => TRUE, '!IE' => TRUE),
- )), TRUE);
$this->assertEqual($new_css, $original_css + array($expected['css'] => 1), t('Page state now has the %css file.', array('%css' => $expected['css'])));
$this->assertCommand($commands, array('data' => $expected_css_html), t('Page now has the %css file.', array('%css' => $expected['css'])));
@@ -170,10 +192,30 @@ class AJAXFrameworkTestCase extends AJAXTestCase {
// string containing the SCRIPT tag, we also ensure that unexpected
// JavaScript code, such as a jQuery.extend() that would potentially clobber
// rather than properly merge settings, didn't accidentally get added.
- $expected_js_html = drupal_get_js('header', array($expected['js'] => drupal_js_defaults($expected['js'])), TRUE);
$this->assertEqual($new_js, $original_js + array($expected['js'] => 1), t('Page state now has the %js file.', array('%js' => $expected['js'])));
$this->assertCommand($commands, array('data' => $expected_js_html), t('Page now has the %js file.', array('%js' => $expected['js'])));
}
+
+ /**
+ * Tests that overridden CSS files are not added during lazy load.
+ */
+ function testLazyLoadOverriddenCSS() {
+ // The test theme overrides system.base.css without an implementation,
+ // thereby removing it.
+ theme_enable(array('test_theme'));
+ variable_set('theme_default', 'test_theme');
+
+ // This gets the form, and emulates an Ajax submission on it, including
+ // adding markup to the HEAD and BODY for any lazy loaded JS/CSS files.
+ $this->drupalPostAJAX('ajax_forms_test_lazy_load_form', array('add_files' => TRUE), array('op' => t('Submit')));
+
+ // Verify that the resulting HTML does not load the overridden CSS file.
+ // We add a "?" to the assertion, because Drupal.settings may include
+ // information about the file; we only really care about whether it appears
+ // in a LINK or STYLE tag, for which Drupal always adds a query string for
+ // cache control.
+ $this->assertNoText('system.base.css?', 'Ajax lazy loading does not add overridden CSS files.');
+ }
}
/**
diff --git a/modules/simpletest/tests/ajax_forms_test.module b/modules/simpletest/tests/ajax_forms_test.module
index 075b005ea..6a95710a8 100644
--- a/modules/simpletest/tests/ajax_forms_test.module
+++ b/modules/simpletest/tests/ajax_forms_test.module
@@ -468,6 +468,10 @@ function ajax_forms_test_validation_form_callback($form, $form_state) {
* Form builder: Builds a form that triggers a simple AJAX callback.
*/
function ajax_forms_test_lazy_load_form($form, &$form_state) {
+ $form['add_files'] = array(
+ '#type' => 'checkbox',
+ '#default_value' => FALSE,
+ );
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
@@ -482,9 +486,11 @@ function ajax_forms_test_lazy_load_form($form, &$form_state) {
* Form submit handler: Adds JavaScript and CSS that wasn't on the original form.
*/
function ajax_forms_test_lazy_load_form_submit($form, &$form_state) {
- drupal_add_js(array('ajax_forms_test_lazy_load_form_submit' => 'executed'), 'setting');
- drupal_add_css(drupal_get_path('module', 'system') . '/system.admin.css');
- drupal_add_js(drupal_get_path('module', 'system') . '/system.js');
+ if ($form_state['values']['add_files']) {
+ drupal_add_js(array('ajax_forms_test_lazy_load_form_submit' => 'executed'), 'setting');
+ drupal_add_css(drupal_get_path('module', 'system') . '/system.admin.css');
+ drupal_add_js(drupal_get_path('module', 'system') . '/system.js');
+ }
$form_state['rebuild'] = TRUE;
}
diff --git a/modules/simpletest/tests/ajax_test.module b/modules/simpletest/tests/ajax_test.module
index 4148a0839..21be01942 100644
--- a/modules/simpletest/tests/ajax_test.module
+++ b/modules/simpletest/tests/ajax_test.module
@@ -32,6 +32,14 @@ function ajax_test_menu() {
}
/**
+ * Implements hook_system_theme_info().
+ */
+function ajax_test_system_theme_info() {
+ $themes['test_theme'] = drupal_get_path('module', 'ajax_test') . '/themes/test_theme/test_theme.info';
+ return $themes;
+}
+
+/**
* Menu callback; Return an element suitable for use by ajax_deliver().
*
* Additionally ensures that ajax_render() incorporates JavaScript settings
diff --git a/modules/simpletest/tests/cache.test b/modules/simpletest/tests/cache.test
index d292fa661..47f2df318 100644
--- a/modules/simpletest/tests/cache.test
+++ b/modules/simpletest/tests/cache.test
@@ -339,6 +339,40 @@ class CacheClearCase extends CacheTestCase {
$this->assertFalse($this->checkCacheExists($id, $this->default_value, $bin), t('All cache entries removed from @bin.', array('@bin' => $bin)));
}
}
+
+ /**
+ * Test minimum cache lifetime.
+ */
+ function testMinimumCacheLifetime() {
+ // Set a minimum/maximum cache lifetime.
+ $this->setupLifetime(300);
+ // Login as a newly-created user.
+ $account = $this->drupalCreateUser(array());
+ $this->drupalLogin($account);
+
+ // Set two cache objects in different bins.
+ $data = $this->randomName(100);
+ cache_set($data, $data, 'cache', CACHE_TEMPORARY);
+ $cached = cache_get($data);
+ $this->assertTrue(isset($cached->data) && $cached->data === $data, 'Cached item retrieved.');
+ cache_set($data, $data, 'cache_page', CACHE_TEMPORARY);
+
+ // Expire temporary items in the 'page' bin.
+ cache_clear_all(NULL, 'cache_page');
+
+ // Since the database cache uses REQUEST_TIME, set the $_SESSION variable
+ // manually to force it to the current time.
+ $_SESSION['cache_expiration']['cache_page'] = time();
+
+ // Items in the default cache bin should not be expired.
+ $cached = cache_get($data);
+ $this->assertTrue(isset($cached->data) && $cached->data == $data, 'Cached item retrieved');
+
+ // Despite the minimum cache lifetime, the item in the 'page' bin should
+ // be invalidated for the current user.
+ $cached = cache_get($data, 'cache_page');
+ $this->assertFalse($cached, 'Cached item was invalidated');
+ }
}
/**
diff --git a/modules/simpletest/tests/common.test b/modules/simpletest/tests/common.test
index 5650d8c01..437b67cd1 100644
--- a/modules/simpletest/tests/common.test
+++ b/modules/simpletest/tests/common.test
@@ -353,7 +353,7 @@ class CommonURLUnitTest extends DrupalWebTestCase {
}
/**
- * Tests for the check_plain(), filter_xss() and format_string() functions.
+ * Tests for check_plain(), filter_xss(), format_string(), and check_url().
*/
class CommonXssUnitTest extends DrupalUnitTestCase {
@@ -424,6 +424,9 @@ class CommonXssUnitTest extends DrupalUnitTestCase {
}
}
+/**
+ * Tests file size parsing and formatting functions.
+ */
class CommonSizeTestCase extends DrupalUnitTestCase {
protected $exact_test_cases;
protected $rounded_test_cases;
@@ -935,7 +938,7 @@ class DrupalHTTPRequestTestCase extends DrupalWebTestCase {
}
function setUp() {
- parent::setUp('system_test');
+ parent::setUp('system_test', 'locale');
}
function testDrupalHTTPRequest() {
@@ -1032,6 +1035,22 @@ class DrupalHTTPRequestTestCase extends DrupalWebTestCase {
$multiple_redirect_3 = drupal_http_request(url('system-test/multiple-redirects/3', array('absolute' => TRUE)), array('max_redirects' => 3));
$this->assertEqual($multiple_redirect_3->redirect_url, $multiple_redirect_final_url, t('redirect_url contains the final redirection location after 3 redirects.'));
}
+
+ /**
+ * Tests Content-language headers generated by Drupal.
+ */
+ function testDrupalHTTPRequestHeaders() {
+ // Check the default header.
+ $request = drupal_http_request(url('<front>', array('absolute' => TRUE)));
+ $this->assertEqual($request->headers['content-language'], 'en', 'Content-Language HTTP header is English.');
+
+ // Add German language and set as default.
+ locale_add_language('de', 'German', 'Deutsch', LANGUAGE_LTR, '', '', TRUE, TRUE);
+
+ // Request front page and check for matching Content-Language.
+ $request = drupal_http_request(url('<front>', array('absolute' => TRUE)));
+ $this->assertEqual($request->headers['content-language'], 'de', 'Content-Language HTTP header is German.');
+ }
}
/**
@@ -1324,6 +1343,48 @@ class JavaScriptTestCase extends DrupalWebTestCase {
}
/**
+ * Tests JavaScript aggregation when files are added to a different scope.
+ */
+ function testAggregationOrder() {
+ // Enable JavaScript aggregation.
+ variable_set('preprocess_js', 1);
+ drupal_static_reset('drupal_add_js');
+
+ // Add two JavaScript files to the current request and build the cache.
+ drupal_add_js('misc/ajax.js');
+ drupal_add_js('misc/autocomplete.js');
+
+ $js_items = drupal_add_js();
+ drupal_build_js_cache(array(
+ 'misc/ajax.js' => $js_items['misc/ajax.js'],
+ 'misc/autocomplete.js' => $js_items['misc/autocomplete.js']
+ ));
+
+ // Store the expected key for the first item in the cache.
+ $cache = array_keys(variable_get('drupal_js_cache_files', array()));
+ $expected_key = $cache[0];
+
+ // Reset variables and add a file in a different scope first.
+ variable_del('drupal_js_cache_files');
+ drupal_static_reset('drupal_add_js');
+ drupal_add_js('some/custom/javascript_file.js', array('scope' => 'footer'));
+ drupal_add_js('misc/ajax.js');
+ drupal_add_js('misc/autocomplete.js');
+
+ // Rebuild the cache.
+ $js_items = drupal_add_js();
+ drupal_build_js_cache(array(
+ 'misc/ajax.js' => $js_items['misc/ajax.js'],
+ 'misc/autocomplete.js' => $js_items['misc/autocomplete.js']
+ ));
+
+ // Compare the expected key for the first file to the current one.
+ $cache = array_keys(variable_get('drupal_js_cache_files', array()));
+ $key = $cache[0];
+ $this->assertEqual($key, $expected_key, 'JavaScript aggregation is not affected by ordering in different scopes.');
+ }
+
+ /**
* Test JavaScript ordering.
*/
function testRenderOrder() {
diff --git a/modules/simpletest/tests/database_test.install b/modules/simpletest/tests/database_test.install
index 4dce2b19a..867d81323 100644
--- a/modules/simpletest/tests/database_test.install
+++ b/modules/simpletest/tests/database_test.install
@@ -28,6 +28,7 @@ function database_test_schema() {
'length' => 255,
'not null' => TRUE,
'default' => '',
+ 'binary' => TRUE,
),
'age' => array(
'description' => "The person's age",
diff --git a/modules/simpletest/tests/database_test.test b/modules/simpletest/tests/database_test.test
index 7b15cf3fa..660833606 100644
--- a/modules/simpletest/tests/database_test.test
+++ b/modules/simpletest/tests/database_test.test
@@ -2065,6 +2065,7 @@ class DatabaseSelectComplexTestCase extends DatabaseTestCase {
function testHavingCountQuery() {
$query = db_select('test')
->extend('PagerDefault')
+ ->groupBy('age')
->having('age + 1 > 0');
$query->addField('test', 'age');
$query->addExpression('age + 1');
@@ -3121,6 +3122,39 @@ class DatabaseBasicSyntaxTestCase extends DatabaseTestCase {
}
/**
+ * Test case sensitivity handling.
+ */
+class DatabaseCaseSensitivityTestCase extends DatabaseTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Case sensitivity',
+ 'description' => 'Test handling case sensitive collation.',
+ 'group' => 'Database',
+ );
+ }
+
+ /**
+ * Test BINARY collation in MySQL.
+ */
+ function testCaseSensitiveInsert() {
+ $num_records_before = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
+
+ $john = db_insert('test')
+ ->fields(array(
+ 'name' => 'john', // <- A record already exists with name 'John'.
+ 'age' => 2,
+ 'job' => 'Baby',
+ ))
+ ->execute();
+
+ $num_records_after = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
+ $this->assertIdentical($num_records_before + 1, (int) $num_records_after, t('Record inserts correctly.'));
+ $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'john'))->fetchField();
+ $this->assertIdentical($saved_age, '2', t('Can retrieve after inserting.'));
+ }
+}
+
+/**
* Test invalid data handling.
*/
class DatabaseInvalidDataTestCase extends DatabaseTestCase {
diff --git a/modules/simpletest/tests/entity_query.test b/modules/simpletest/tests/entity_query.test
index d5e5524f2..ddfd35433 100644
--- a/modules/simpletest/tests/entity_query.test
+++ b/modules/simpletest/tests/entity_query.test
@@ -1409,6 +1409,27 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
}
/**
+ * Tests disabling the pager in EntityFieldQuery.
+ */
+ function testEntityFieldQueryDisablePager() {
+ // Test enabling a pager and then disabling it.
+ $query = new EntityFieldQuery();
+ $query
+ ->entityCondition('entity_type', 'test_entity_bundle_key')
+ ->propertyOrderBy('ftid', 'ASC')
+ ->pager(1)
+ ->pager(0);
+ $this->assertEntityFieldQuery($query, array(
+ array('test_entity_bundle_key', 1),
+ array('test_entity_bundle_key', 2),
+ array('test_entity_bundle_key', 3),
+ array('test_entity_bundle_key', 4),
+ array('test_entity_bundle_key', 5),
+ array('test_entity_bundle_key', 6),
+ ), 'All test entities are listed when the pager is enabled and then disabled.', TRUE);
+ }
+
+ /**
* Tests the TableSort integration of EntityFieldQuery.
*/
function testEntityFieldQueryTableSort() {
diff --git a/modules/simpletest/tests/error.test b/modules/simpletest/tests/error.test
index b1ec4b3f5..5b6b04b9e 100644
--- a/modules/simpletest/tests/error.test
+++ b/modules/simpletest/tests/error.test
@@ -3,7 +3,7 @@
/**
* Tests Drupal error and exception handlers.
*/
-class DrupalErrorHandlerUnitTest extends DrupalWebTestCase {
+class DrupalErrorHandlerTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Drupal error handlers',
diff --git a/modules/simpletest/tests/file.test b/modules/simpletest/tests/file.test
index 4c56bfcce..3df31ba5f 100644
--- a/modules/simpletest/tests/file.test
+++ b/modules/simpletest/tests/file.test
@@ -2026,6 +2026,19 @@ class FileSaveTest extends FileHookTestCase {
$loaded_file = db_query('SELECT * FROM {file_managed} f WHERE f.fid = :fid', array(':fid' => $saved_file->fid))->fetch(PDO::FETCH_OBJ);
$this->assertNotNull($loaded_file, t("Record still exists in the database."), 'File');
$this->assertEqual($loaded_file->status, $saved_file->status, t("Status was saved correctly."));
+
+ // Try to insert a second file with the same name apart from case insensitivity
+ // to ensure the 'uri' index allows for filenames with different cases.
+ $file = (object) array(
+ 'uid' => 1,
+ 'filename' => 'DRUPLICON.txt',
+ 'uri' => 'public://DRUPLICON.txt',
+ 'filemime' => 'text/plain',
+ 'timestamp' => 1,
+ 'status' => FILE_STATUS_PERMANENT,
+ );
+ file_put_contents($file->uri, 'hello world');
+ file_save($file);
}
}
diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test
index 13fdca201..2f5a9cd14 100644
--- a/modules/simpletest/tests/form.test
+++ b/modules/simpletest/tests/form.test
@@ -122,6 +122,72 @@ class FormsTestCase extends DrupalWebTestCase {
}
/**
+ * Tests validation for required checkbox, select, and radio elements.
+ *
+ * Submits a test form containing several types of form elements. The form
+ * is submitted twice, first without values for required fields and then
+ * with values. Each submission is checked for relevant error messages.
+ *
+ * @see form_test_validate_required_form()
+ */
+ function testRequiredCheckboxesRadio() {
+ $form = $form_state = array();
+ $form = form_test_validate_required_form($form, $form_state);
+
+ // Attempt to submit the form with no required fields set.
+ $edit = array();
+ $this->drupalPost('form-test/validate-required', $edit, 'Submit');
+
+ // The only error messages that should appear are the relevant 'required'
+ // messages for each field.
+ $expected = array();
+ foreach (array('textfield', 'checkboxes', 'select', 'radios') as $key) {
+ $expected[] = t('!name field is required.', array('!name' => $form[$key]['#title']));
+ }
+
+ // Check the page for error messages.
+ $errors = $this->xpath('//div[contains(@class, "error")]//li');
+ foreach ($errors as $error) {
+ $expected_key = array_search($error[0], $expected);
+ // If the error message is not one of the expected messages, fail.
+ if ($expected_key === FALSE) {
+ $this->fail(format_string("Unexpected error message: @error", array('@error' => $error[0])));
+ }
+ // Remove the expected message from the list once it is found.
+ else {
+ unset($expected[$expected_key]);
+ }
+ }
+
+ // Fail if any expected messages were not found.
+ foreach ($expected as $not_found) {
+ $this->fail(format_string("Found error message: @error", array('@error' => $not_found)));
+ }
+
+ // Verify that input elements are still empty.
+ $this->assertFieldByName('textfield', '');
+ $this->assertNoFieldChecked('edit-checkboxes-foo');
+ $this->assertNoFieldChecked('edit-checkboxes-bar');
+ $this->assertOptionSelected('edit-select', '');
+ $this->assertNoFieldChecked('edit-radios-foo');
+ $this->assertNoFieldChecked('edit-radios-bar');
+ $this->assertNoFieldChecked('edit-radios-optional-foo');
+ $this->assertNoFieldChecked('edit-radios-optional-bar');
+
+ // Submit again with required fields set and verify that there are no
+ // error messages.
+ $edit = array(
+ 'textfield' => $this->randomString(),
+ 'checkboxes[foo]' => TRUE,
+ 'select' => 'foo',
+ 'radios' => 'bar',
+ );
+ $this->drupalPost(NULL, $edit, 'Submit');
+ $this->assertNoFieldByXpath('//div[contains(@class, "error")]', FALSE, 'No error message is displayed when all required fields are filled.');
+ $this->assertRaw("The form_test_validate_required_form form was submitted successfully.", 'Validation form submitted successfully.');
+ }
+
+ /**
* Test default value handling for checkboxes.
*
* @see _form_test_checkbox()
@@ -600,12 +666,12 @@ class FormsElementsLabelsTestCase extends DrupalWebTestCase {
$this->assertTrue(isset($elements[0]), t("Label 0 found radios."));
// Exercise various defaults for checkboxes and modifications to ensure
- // appropriate override and correct behaviour.
+ // appropriate override and correct behavior.
$elements = $this->xpath('//input[@id="edit-form-checkbox-test"]/following-sibling::label[@for="edit-form-checkbox-test" and @class="option"]');
$this->assertTrue(isset($elements[0]), t("Label follows field and label option class correct for a checkbox by default."));
// Exercise various defaults for textboxes and modifications to ensure
- // appropriate override and correct behaviour.
+ // appropriate override and correct behavior.
$elements = $this->xpath('//label[@for="edit-form-textfield-test-title-and-required"]/child::span[@class="form-required"]/parent::*/following-sibling::input[@id="edit-form-textfield-test-title-and-required"]');
$this->assertTrue(isset($elements[0]), t("Label precedes textfield, with required marker inside label."));
@@ -637,6 +703,12 @@ class FormsElementsLabelsTestCase extends DrupalWebTestCase {
$elements = $this->xpath('//div[@id="form-test-textfield-title-suffix"]/preceding-sibling::div[contains(@class, \'form-item-form-textfield-test-title\')]');
$this->assertTrue(isset($elements[0]), t("Properly places the #suffix element before the form item."));
+
+ // Check title attribute for radios and checkboxes.
+ $elements = $this->xpath('//div[@id="edit-form-checkboxes-title-attribute"]');
+ $this->assertEqual($elements[0]['title'], 'Checkboxes test' . ' (' . t('Required') . ')', 'Title attribute found.');
+ $elements = $this->xpath('//div[@id="edit-form-radios-title-attribute"]');
+ $this->assertEqual($elements[0]['title'], 'Radios test' . ' (' . t('Required') . ')', 'Title attribute found.');
}
}
diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module
index 0a748d2df..43a6cbecb 100644
--- a/modules/simpletest/tests/form_test.module
+++ b/modules/simpletest/tests/form_test.module
@@ -23,6 +23,13 @@ function form_test_menu() {
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
+ $items['form-test/validate-required'] = array(
+ 'title' => 'Form #required validation',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('form_test_validate_required_form'),
+ 'access callback' => TRUE,
+ 'type' => MENU_CALLBACK,
+ );
$items['form-test/limit-validation-errors'] = array(
'title' => 'Form validation with some error suppression',
'page callback' => 'drupal_get_form',
@@ -332,6 +339,52 @@ function form_test_validate_form_validate(&$form, &$form_state) {
}
/**
+ * Form constructor to test the #required property.
+ */
+function form_test_validate_required_form($form, &$form_state) {
+ $options = drupal_map_assoc(array('foo', 'bar'));
+
+ $form['textfield'] = array(
+ '#type' => 'textfield',
+ '#title' => 'Textfield',
+ '#required' => TRUE,
+ );
+ $form['checkboxes'] = array(
+ '#type' => 'checkboxes',
+ '#title' => 'Checkboxes',
+ '#options' => $options,
+ '#required' => TRUE,
+ );
+ $form['select'] = array(
+ '#type' => 'select',
+ '#title' => 'Select',
+ '#options' => $options,
+ '#required' => TRUE,
+ );
+ $form['radios'] = array(
+ '#type' => 'radios',
+ '#title' => 'Radios',
+ '#options' => $options,
+ '#required' => TRUE,
+ );
+ $form['radios_optional'] = array(
+ '#type' => 'radios',
+ '#title' => 'Radios (optional)',
+ '#options' => $options,
+ );
+ $form['actions'] = array('#type' => 'actions');
+ $form['actions']['submit'] = array('#type' => 'submit', '#value' => 'Submit');
+ return $form;
+}
+
+/**
+ * Form submission handler for form_test_validate_required_form().
+ */
+function form_test_validate_required_form_submit($form, &$form_state) {
+ drupal_set_message('The form_test_validate_required_form form was submitted successfully.');
+}
+
+/**
* Builds a simple form with a button triggering partial validation.
*/
function form_test_limit_validation_errors_form($form, &$form_state) {
@@ -738,10 +791,31 @@ function form_label_test_form() {
'#title' => t('Textfield test for invisible title'),
'#title_display' => 'invisible',
);
- // Textfield test for title set not to display
+ // Textfield test for title set not to display.
$form['form_textfield_test_title_no_show'] = array(
'#type' => 'textfield',
);
+ // Checkboxes & radios with title as attribute.
+ $form['form_checkboxes_title_attribute'] = array(
+ '#type' => 'checkboxes',
+ '#title' => 'Checkboxes test',
+ '#options' => array(
+ 'first-checkbox' => 'First checkbox',
+ 'second-checkbox' => 'Second checkbox',
+ ),
+ '#title_display' => 'attribute',
+ '#required' => TRUE,
+ );
+ $form['form_radios_title_attribute'] = array(
+ '#type' => 'radios',
+ '#title' => 'Radios test',
+ '#options' => array(
+ 'first-radio' => 'First radio',
+ 'second-radio' => 'Second radio',
+ ),
+ '#title_display' => 'attribute',
+ '#required' => TRUE,
+ );
return $form;
}
diff --git a/modules/simpletest/tests/image.test b/modules/simpletest/tests/image.test
index 60599bee5..962aa661f 100644
--- a/modules/simpletest/tests/image.test
+++ b/modules/simpletest/tests/image.test
@@ -458,3 +458,44 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
}
}
+
+/**
+ * Tests the file move function for managed files.
+ */
+class ImageFileMoveTest extends ImageToolkitTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Image moving',
+ 'description' => 'Tests the file move function for managed files.',
+ 'group' => 'Image',
+ );
+ }
+
+ /**
+ * Tests moving a randomly generated image.
+ */
+ function testNormal() {
+ // Pick a file for testing.
+ $file = current($this->drupalGetTestFiles('image'));
+
+ // Create derivative image.
+ $style = image_style_load(key(image_styles()));
+ $derivative_uri = image_style_path($style['name'], $file->uri);
+ image_style_create_derivative($style, $file->uri, $derivative_uri);
+
+ // Check if derivative image exists.
+ $this->assertTrue(file_exists($derivative_uri), 'Make sure derivative image is generated successfully.');
+
+ // Clone the object so we don't have to worry about the function changing
+ // our reference copy.
+ $desired_filepath = 'public://' . $this->randomName();
+ $result = file_move(clone $file, $desired_filepath, FILE_EXISTS_ERROR);
+
+ // Check if image has been moved.
+ $this->assertTrue(file_exists($result->uri), 'Make sure image is moved successfully.');
+
+ // Check if derivative image has been flushed.
+ $this->assertFalse(file_exists($derivative_uri), 'Make sure derivative image has been flushed.');
+ }
+}
+
diff --git a/modules/simpletest/tests/menu.test b/modules/simpletest/tests/menu.test
index b12ccb116..a7fb8a484 100644
--- a/modules/simpletest/tests/menu.test
+++ b/modules/simpletest/tests/menu.test
@@ -1139,6 +1139,7 @@ class MenuBreadcrumbTestCase extends MenuWebTestCase {
$trail += array(
'admin/structure/menu/manage/navigation' => t('Navigation'),
);
+ $this->assertBreadcrumb("admin/structure/menu/item/6/edit", $trail);
$this->assertBreadcrumb('admin/structure/menu/manage/navigation/edit', $trail);
$this->assertBreadcrumb('admin/structure/menu/manage/navigation/add', $trail);
@@ -1643,4 +1644,97 @@ class MenuTrailTestCase extends MenuWebTestCase {
variable_set('menu_test_menu_tree_set_path', $test_menu_path);
$this->assertBreadcrumb('admin/config/development/menu-trail', $override_breadcrumb, t('Menu trail - Case 2'), $override_tree);
}
+
+ /**
+ * Tests that the active trail works correctly on custom 403 and 404 pages.
+ */
+ function testCustom403And404Pages() {
+ // Set the custom 403 and 404 pages we will use.
+ variable_set('site_403', 'menu-test/custom-403-page');
+ variable_set('site_404', 'menu-test/custom-404-page');
+
+ // Define the paths we'll visit to trigger 403 and 404 responses during
+ // this test, and the expected active trail for each case.
+ $paths = array(
+ 403 => 'admin/config',
+ 404 => $this->randomName(),
+ );
+ // For the 403 page, the initial trail during the Drupal bootstrap should
+ // include the page that the user is trying to visit, while the final trail
+ // should reflect the custom 403 page that the user was redirected to.
+ $expected_trail[403]['initial'] = array(
+ '<front>' => 'Home',
+ 'admin/config' => 'Configuration',
+ );
+ $expected_trail[403]['final'] = array(
+ '<front>' => 'Home',
+ 'menu-test' => 'Menu test root',
+ 'menu-test/custom-403-page' => 'Custom 403 page',
+ );
+ // For the 404 page, the initial trail during the Drupal bootstrap should
+ // only contain the link back to "Home" (since the page the user is trying
+ // to visit doesn't have any menu items associated with it), while the
+ // final trail should reflect the custom 404 page that the user was
+ // redirected to.
+ $expected_trail[404]['initial'] = array(
+ '<front>' => 'Home',
+ );
+ $expected_trail[404]['final'] = array(
+ '<front>' => 'Home',
+ 'menu-test' => 'Menu test root',
+ 'menu-test/custom-404-page' => 'Custom 404 page',
+ );
+
+ // Visit each path as an anonymous user so that we will actually get a 403
+ // on admin/config.
+ $this->drupalLogout();
+ foreach (array(403, 404) as $status_code) {
+ // Before visiting the page, trigger the code in the menu_test module
+ // that will record the active trail (so we can check it in this test).
+ variable_set('menu_test_record_active_trail', TRUE);
+ $this->drupalGet($paths[$status_code]);
+ $this->assertResponse($status_code);
+
+ // Check that the initial trail (during the Drupal bootstrap) matches
+ // what we expect.
+ $initial_trail = variable_get('menu_test_active_trail_initial', array());
+ $this->assertEqual(count($initial_trail), count($expected_trail[$status_code]['initial']), t('The initial active trail for a @status_code page contains the expected number of items (expected: @expected, found: @found).', array(
+ '@status_code' => $status_code,
+ '@expected' => count($expected_trail[$status_code]['initial']),
+ '@found' => count($initial_trail),
+ )));
+ foreach (array_keys($expected_trail[$status_code]['initial']) as $index => $path) {
+ $this->assertEqual($initial_trail[$index]['href'], $path, t('Element number @number of the initial active trail for a @status_code page contains the correct path (expected: @expected, found: @found)', array(
+ '@number' => $index + 1,
+ '@status_code' => $status_code,
+ '@expected' => $path,
+ '@found' => $initial_trail[$index]['href'],
+ )));
+ }
+
+ // Check that the final trail (after the user has been redirected to the
+ // custom 403/404 page) matches what we expect.
+ $final_trail = variable_get('menu_test_active_trail_final', array());
+ $this->assertEqual(count($final_trail), count($expected_trail[$status_code]['final']), t('The final active trail for a @status_code page contains the expected number of items (expected: @expected, found: @found).', array(
+ '@status_code' => $status_code,
+ '@expected' => count($expected_trail[$status_code]['final']),
+ '@found' => count($final_trail),
+ )));
+ foreach (array_keys($expected_trail[$status_code]['final']) as $index => $path) {
+ $this->assertEqual($final_trail[$index]['href'], $path, t('Element number @number of the final active trail for a @status_code page contains the correct path (expected: @expected, found: @found)', array(
+ '@number' => $index + 1,
+ '@status_code' => $status_code,
+ '@expected' => $path,
+ '@found' => $final_trail[$index]['href'],
+ )));
+ }
+
+ // Check that the breadcrumb displayed on the final custom 403/404 page
+ // matches what we expect. (The last item of the active trail represents
+ // the current page, which is not supposed to appear in the breadcrumb,
+ // so we need to remove it from the array before checking.)
+ array_pop($expected_trail[$status_code]['final']);
+ $this->assertBreadcrumb(NULL, $expected_trail[$status_code]['final']);
+ }
+ }
}
diff --git a/modules/simpletest/tests/menu_test.module b/modules/simpletest/tests/menu_test.module
index c42aca60f..0b954ae1c 100644
--- a/modules/simpletest/tests/menu_test.module
+++ b/modules/simpletest/tests/menu_test.module
@@ -230,6 +230,16 @@ function menu_test_menu() {
'page callback' => 'menu_test_menu_trail_callback',
'access arguments' => array('access administration pages'),
);
+ $items['menu-test/custom-403-page'] = array(
+ 'title' => 'Custom 403 page',
+ 'page callback' => 'menu_test_custom_403_404_callback',
+ 'access arguments' => array('access content'),
+ );
+ $items['menu-test/custom-404-page'] = array(
+ 'title' => 'Custom 404 page',
+ 'page callback' => 'menu_test_custom_403_404_callback',
+ 'access arguments' => array('access content'),
+ );
// File inheritance tests. This menu item should inherit the page callback
// system_admin_menu_block_page() and therefore render its children as links
@@ -370,6 +380,32 @@ function menu_test_menu_trail_callback() {
}
/**
+ * Implements hook_init().
+ */
+function menu_test_init() {
+ // When requested by one of the MenuTrailTestCase tests, record the initial
+ // active trail during Drupal's bootstrap (before the user is redirected to a
+ // custom 403 or 404 page). See menu_test_custom_403_404_callback().
+ if (variable_get('menu_test_record_active_trail', FALSE)) {
+ variable_set('menu_test_active_trail_initial', menu_get_active_trail());
+ }
+}
+
+/**
+ * Callback for our custom 403 and 404 pages.
+ */
+function menu_test_custom_403_404_callback() {
+ // When requested by one of the MenuTrailTestCase tests, record the final
+ // active trail now that the user has been redirected to the custom 403 or
+ // 404 page. See menu_test_init().
+ if (variable_get('menu_test_record_active_trail', FALSE)) {
+ variable_set('menu_test_active_trail_final', menu_get_active_trail());
+ }
+
+ return 'This is menu_test_custom_403_404_callback().';
+}
+
+/**
* Page callback to use when testing the theme callback functionality.
*
* @param $inherited
diff --git a/modules/simpletest/tests/pager.test b/modules/simpletest/tests/pager.test
new file mode 100644
index 000000000..6fdeec5bf
--- /dev/null
+++ b/modules/simpletest/tests/pager.test
@@ -0,0 +1,159 @@
+<?php
+
+/**
+ * @file
+ * Tests for pager functionality.
+ */
+
+/**
+ * Tests pager functionality.
+ */
+class PagerFunctionalWebTestCase extends DrupalWebTestCase {
+ protected $profile = 'testing';
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Pager functionality',
+ 'description' => 'Tests pager functionality.',
+ 'group' => 'Pager',
+ );
+ }
+
+ function setUp() {
+ parent::setUp(array('dblog'));
+
+ // Insert 300 log messages.
+ for ($i = 0; $i < 300; $i++) {
+ watchdog('pager_test', $this->randomString(), NULL, WATCHDOG_DEBUG);
+ }
+
+ $this->admin_user = $this->drupalCreateUser(array(
+ 'access site reports',
+ ));
+ $this->drupalLogin($this->admin_user);
+ }
+
+ /**
+ * Tests markup and CSS classes of pager links.
+ */
+ function testActiveClass() {
+ // Verify first page.
+ $this->drupalGet('admin/reports/dblog');
+ $current_page = 0;
+ $this->assertPagerItems($current_page);
+
+ // Verify any page but first/last.
+ $current_page++;
+ $this->drupalGet('admin/reports/dblog', array('query' => array('page' => $current_page)));
+ $this->assertPagerItems($current_page);
+
+ // Verify last page.
+ $elements = $this->xpath('//li[contains(@class, :class)]/a', array(':class' => 'pager-last'));
+ preg_match('@page=(\d+)@', $elements[0]['href'], $matches);
+ $current_page = (int) $matches[1];
+ $this->drupalGet($GLOBALS['base_root'] . $elements[0]['href'], array('external' => TRUE));
+ $this->assertPagerItems($current_page);
+ }
+
+ /**
+ * Asserts pager items and links.
+ *
+ * @param int $current_page
+ * The current pager page the internal browser is on.
+ */
+ protected function assertPagerItems($current_page) {
+ $elements = $this->xpath('//ul[@class=:class]/li', array(':class' => 'pager'));
+ $this->assertTrue(!empty($elements), 'Pager found.');
+
+ // Make current page 1-based.
+ $current_page++;
+
+ // Extract first/previous and next/last items.
+ // first/previous only exist, if the current page is not the first.
+ if ($current_page > 1) {
+ $first = array_shift($elements);
+ $previous = array_shift($elements);
+ }
+ // next/last always exist, unless the current page is the last.
+ if ($current_page != count($elements)) {
+ $last = array_pop($elements);
+ $next = array_pop($elements);
+ }
+
+ // Verify items and links to pages.
+ foreach ($elements as $page => $element) {
+ // Make item/page index 1-based.
+ $page++;
+ if ($current_page == $page) {
+ $this->assertClass($element, 'pager-current', 'Item for current page has .pager-current class.');
+ $this->assertFalse(isset($element->a), 'Item for current page has no link.');
+ }
+ else {
+ $this->assertNoClass($element, 'pager-current', "Item for page $page has no .pager-current class.");
+ $this->assertClass($element, 'pager-item', "Item for page $page has .pager-item class.");
+ $this->assertTrue($element->a, "Link to page $page found.");
+ $this->assertNoClass($element->a, 'active', "Link to page $page is not active.");
+ }
+ unset($elements[--$page]);
+ }
+ // Verify that no other items remain untested.
+ $this->assertTrue(empty($elements), 'All expected items found.');
+
+ // Verify first/previous and next/last items and links.
+ if (isset($first)) {
+ $this->assertClass($first, 'pager-first', "Item for first page has .pager-first class.");
+ $this->assertTrue($first->a, "Link to first page found.");
+ $this->assertNoClass($first->a, 'active', "Link to first page is not active.");
+ }
+ if (isset($previous)) {
+ $this->assertClass($previous, 'pager-previous', "Item for first page has .pager-previous class.");
+ $this->assertTrue($previous->a, "Link to previous page found.");
+ $this->assertNoClass($previous->a, 'active', "Link to previous page is not active.");
+ }
+ if (isset($next)) {
+ $this->assertClass($next, 'pager-next', "Item for next page has .pager-next class.");
+ $this->assertTrue($next->a, "Link to next page found.");
+ $this->assertNoClass($next->a, 'active', "Link to next page is not active.");
+ }
+ if (isset($last)) {
+ $this->assertClass($last, 'pager-last', "Item for last page has .pager-last class.");
+ $this->assertTrue($last->a, "Link to last page found.");
+ $this->assertNoClass($last->a, 'active', "Link to last page is not active.");
+ }
+ }
+
+ /**
+ * Asserts that an element has a given class.
+ *
+ * @param SimpleXMLElement $element
+ * The element to test.
+ * @param string $class
+ * The class to assert.
+ * @param string $message
+ * (optional) A verbose message to output.
+ */
+ protected function assertClass(SimpleXMLElement $element, $class, $message = NULL) {
+ if (!isset($message)) {
+ $message = "Class .$class found.";
+ }
+ $this->assertTrue(strpos($element['class'], $class) !== FALSE, $message);
+ }
+
+ /**
+ * Asserts that an element does not have a given class.
+ *
+ * @param SimpleXMLElement $element
+ * The element to test.
+ * @param string $class
+ * The class to assert.
+ * @param string $message
+ * (optional) A verbose message to output.
+ */
+ protected function assertNoClass(SimpleXMLElement $element, $class, $message = NULL) {
+ if (!isset($message)) {
+ $message = "Class .$class not found.";
+ }
+ $this->assertTrue(strpos($element['class'], $class) === FALSE, $message);
+ }
+}
+
diff --git a/modules/simpletest/tests/path.test b/modules/simpletest/tests/path.test
index 8b3e6dc48..a506349dc 100644
--- a/modules/simpletest/tests/path.test
+++ b/modules/simpletest/tests/path.test
@@ -333,3 +333,49 @@ class PathLookupTest extends DrupalWebTestCase {
$this->assertEqual(drupal_lookup_path('source', $path['alias']), $path['source'], t('Newer alias record is returned when comparing two LANGUAGE_NONE paths with the same alias.'));
}
}
+
+/**
+ * Tests the path_save() function.
+ */
+class PathSaveTest extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => t('Path save'),
+ 'description' => t('Tests that path_save() exposes the previous alias value.'),
+ 'group' => t('Path API'),
+ );
+ }
+
+ function setUp() {
+ // Enable a helper module that implements hook_path_update().
+ parent::setUp('path_test');
+ path_test_reset();
+ }
+
+ /**
+ * Tests that path_save() makes the original path available to modules.
+ */
+ function testDrupalSaveOriginalPath() {
+ $account = $this->drupalCreateUser();
+ $uid = $account->uid;
+ $name = $account->name;
+
+ // Create a language-neutral alias.
+ $path = array(
+ 'source' => "user/$uid",
+ 'alias' => 'foo',
+ );
+ $path_original = $path;
+ path_save($path);
+
+ // Alter the path.
+ $path['alias'] = 'bar';
+ path_save($path);
+
+ // Test to see if the original alias is available to modules during
+ // hook_path_update().
+ $results = variable_get('path_test_results', array());
+ $this->assertIdentical($results['hook_path_update']['original']['alias'], $path_original['alias'], t('Old path alias available to modules during hook_path_update.'));
+ $this->assertIdentical($results['hook_path_update']['original']['source'], $path_original['source'], t('Old path alias available to modules during hook_path_update.'));
+ }
+}
diff --git a/modules/simpletest/tests/path_test.info b/modules/simpletest/tests/path_test.info
new file mode 100644
index 000000000..ea993ae87
--- /dev/null
+++ b/modules/simpletest/tests/path_test.info
@@ -0,0 +1,6 @@
+name = "Hook path tests"
+description = "Support module for path hook testing."
+package = Testing
+version = VERSION
+core = 7.x
+hidden = TRUE
diff --git a/modules/simpletest/tests/path_test.module b/modules/simpletest/tests/path_test.module
new file mode 100644
index 000000000..d3dc80e22
--- /dev/null
+++ b/modules/simpletest/tests/path_test.module
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @file
+ * Helper module for the path tests.
+ */
+
+/**
+ * Resets the path test results.
+ */
+function path_test_reset() {
+ variable_set('path_test_results', array());
+}
+
+/**
+ * Implements hook_path_update().
+ */
+function path_test_path_update($path) {
+ $results = variable_get('path_test_results', array());
+ $results['hook_path_update'] = $path;
+ variable_set('path_test_results', $results);
+}
+
diff --git a/modules/simpletest/tests/session.test b/modules/simpletest/tests/session.test
index bc72e5c5e..e5ceb7538 100644
--- a/modules/simpletest/tests/session.test
+++ b/modules/simpletest/tests/session.test
@@ -455,7 +455,7 @@ class SessionHttpsTestCase extends DrupalWebTestCase {
}
}
- // Test that session data saved before login is not available using the
+ // Test that session data saved before login is not available using the
// pre-login anonymous cookie.
$this->cookies = array();
$this->drupalGet('session-test/get', array('Cookie: ' . $anonymous_cookie));
@@ -471,15 +471,10 @@ class SessionHttpsTestCase extends DrupalWebTestCase {
$this->drupalGet('user');
$form = $this->xpath('//form[@id="user-login"]');
$form[0]['action'] = $this->httpsUrl('user');
- $this->drupalPost(NULL, $edit, t('Log in'), array(), array('Cookie: ' . $secure_session_name . '=' . $this->cookies[$secure_session_name]['value']));
-
- // Get the insecure session cookie set by the secure login POST request.
- $headers = $this->drupalGetHeaders(TRUE);
- strtok($headers[0]['set-cookie'], ';=');
- $session_id = strtok(';=');
+ $this->drupalPost(NULL, $edit, t('Log in'));
// Test that the user is also authenticated on the insecure site.
- $this->drupalGet("user/{$user->uid}/edit", array(), array('Cookie: ' . $insecure_session_name . '=' . $session_id));
+ $this->drupalGet("user/{$user->uid}/edit");
$this->assertResponse(200);
}
diff --git a/modules/simpletest/tests/theme.test b/modules/simpletest/tests/theme.test
index af1141124..ba6440028 100644
--- a/modules/simpletest/tests/theme.test
+++ b/modules/simpletest/tests/theme.test
@@ -8,7 +8,7 @@
/**
* Unit tests for the Theme API.
*/
-class ThemeUnitTest extends DrupalWebTestCase {
+class ThemeTestCase extends DrupalWebTestCase {
protected $profile = 'testing';
public static function getInfo() {
@@ -52,11 +52,19 @@ class ThemeUnitTest extends DrupalWebTestCase {
}
/**
- * Preprocess functions for the base hook should run even for suggestion implementations.
- */
+ * Ensures preprocess functions run even for suggestion implementations.
+ *
+ * The theme hook used by this test has its base preprocess function in a
+ * separate file, so this test also ensures that that file is correctly loaded
+ * when needed.
+ */
function testPreprocessForSuggestions() {
- $this->drupalGet('theme-test/suggestion');
- $this->assertText('test_theme_breadcrumb__suggestion: 1', t('Theme hook suggestion ran with data available from a preprocess function for the base hook.'));
+ // Test with both an unprimed and primed theme registry.
+ drupal_theme_rebuild();
+ for ($i = 0; $i < 2; $i++) {
+ $this->drupalGet('theme-test/suggestion');
+ $this->assertText('Theme hook implementor=test_theme_theme_test__suggestion(). Foo=template_preprocess_theme_test', 'Theme hook suggestion ran with data available from a preprocess function for the base hook.');
+ }
}
/**
@@ -103,12 +111,25 @@ class ThemeUnitTest extends DrupalWebTestCase {
$this->drupalGet('theme-test/suggestion');
variable_set('preprocess_css', 0);
}
+
+ /**
+ * Ensures the theme registry is rebuilt when modules are disabled/enabled.
+ */
+ function testRegistryRebuild() {
+ $this->assertIdentical(theme('theme_test_foo', array('foo' => 'a')), 'a', 'The theme registry contains theme_test_foo.');
+
+ module_disable(array('theme_test'), FALSE);
+ $this->assertIdentical(theme('theme_test_foo', array('foo' => 'b')), '', 'The theme registry does not contain theme_test_foo, because the module is disabled.');
+
+ module_enable(array('theme_test'), FALSE);
+ $this->assertIdentical(theme('theme_test_foo', array('foo' => 'c')), 'c', 'The theme registry contains theme_test_foo again after re-enabling the module.');
+ }
}
/**
* Unit tests for theme_table().
*/
-class ThemeTableUnitTest extends DrupalWebTestCase {
+class ThemeTableTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Theme Table',
@@ -307,7 +328,7 @@ class ThemeLinksTest extends DrupalWebTestCase {
/**
* Functional test for initialization of the theme system in hook_init().
*/
-class ThemeHookInitUnitTest extends DrupalWebTestCase {
+class ThemeHookInitTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Theme initialization in hook_init()',
diff --git a/modules/simpletest/tests/theme_test.inc b/modules/simpletest/tests/theme_test.inc
new file mode 100644
index 000000000..6cde68384
--- /dev/null
+++ b/modules/simpletest/tests/theme_test.inc
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Returns HTML for the 'theme_test' theme hook used by tests.
+ */
+function theme_theme_test($variables) {
+ return 'Theme hook implementor=theme_theme_test(). Foo=' . $variables['foo'];
+}
+
+/**
+ * Preprocesses variables for theme_theme_test().
+ */
+function template_preprocess_theme_test(&$variables) {
+ $variables['foo'] = 'template_preprocess_theme_test';
+}
diff --git a/modules/simpletest/tests/theme_test.module b/modules/simpletest/tests/theme_test.module
index 48e2e83c6..a9bd2ad24 100644
--- a/modules/simpletest/tests/theme_test.module
+++ b/modules/simpletest/tests/theme_test.module
@@ -4,13 +4,19 @@
* Implements hook_theme().
*/
function theme_test_theme($existing, $type, $theme, $path) {
+ $items['theme_test'] = array(
+ 'file' => 'theme_test.inc',
+ 'variables' => array('foo' => ''),
+ );
$items['theme_test_template_test'] = array(
'template' => 'theme_test.template_test',
);
$items['theme_test_template_test_2'] = array(
'template' => 'theme_test.template_test',
);
-
+ $items['theme_test_foo'] = array(
+ 'variables' => array('foo' => NULL),
+ );
return $items;
}
@@ -115,14 +121,12 @@ function _theme_test_alter() {
* Page callback, calls a theme hook suggestion.
*/
function _theme_test_suggestion() {
- return theme(array('breadcrumb__suggestion', 'breadcrumb'), array());
+ return theme(array('theme_test__suggestion', 'theme_test'), array());
}
/**
- * Implements hook_preprocess_breadcrumb().
- *
- * Set a variable that can later be tested to see if this function ran.
+ * Theme function for testing theme('theme_test_foo').
*/
-function theme_test_preprocess_breadcrumb(&$variables) {
- $variables['theme_test_preprocess_breadcrumb'] = 1;
+function theme_theme_test_foo($variables) {
+ return $variables['foo'];
}
diff --git a/modules/simpletest/tests/themes/test_theme/template.php b/modules/simpletest/tests/themes/test_theme/template.php
index ef8118a6d..8275818e4 100644
--- a/modules/simpletest/tests/themes/test_theme/template.php
+++ b/modules/simpletest/tests/themes/test_theme/template.php
@@ -3,10 +3,8 @@
/**
* Tests a theme overriding a suggestion of a base theme hook.
*/
-function test_theme_breadcrumb__suggestion($variables) {
- // Tests that preprocess functions for the base theme hook get called even
- // when the suggestion has an implementation.
- return 'test_theme_breadcrumb__suggestion: ' . $variables['theme_test_preprocess_breadcrumb'];
+function test_theme_theme_test__suggestion($variables) {
+ return 'Theme hook implementor=test_theme_theme_test__suggestion(). Foo=' . $variables['foo'];
}
/**
diff --git a/modules/simpletest/tests/upgrade/drupal-6.trigger.database.php b/modules/simpletest/tests/upgrade/drupal-6.trigger.database.php
new file mode 100644
index 000000000..0962f3582
--- /dev/null
+++ b/modules/simpletest/tests/upgrade/drupal-6.trigger.database.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * @file
+ * Test content for the trigger upgrade path.
+ */
+db_create_table('trigger_assignments', array(
+ 'fields' => array(
+ 'hook' => array(
+ 'type' => 'varchar',
+ 'length' => 32,
+ 'not null' => TRUE,
+ 'default' => '',
+ ),
+ 'op' => array(
+ 'type' => 'varchar',
+ 'length' => 32,
+ 'not null' => TRUE,
+ 'default' => '',
+ ),
+ 'aid' => array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'default' => '',
+ ),
+ 'weight' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ ),
+ ),
+ 'primary key' => array('hook', 'op', 'aid'),
+ 'module' => 'trigger',
+ 'name' => 'trigger_assignments',
+));
+
+
+// Add several trigger configurations.
+db_insert('trigger_assignments')->fields(array(
+ 'hook',
+ 'op',
+ 'aid',
+ 'weight',
+))
+->values(array(
+ 'hook' => 'node',
+ 'op' => 'presave',
+ 'aid' => 'node_publish_action',
+ 'weight' => '1',
+))
+->values(array(
+ 'hook' => 'comment',
+ 'op' => 'presave',
+ 'aid' => 'comment_publish_action',
+ 'weight' => '1',
+))
+->values(array(
+ 'hook' => 'comment_delete',
+ 'op' => 'presave',
+ 'aid' => 'node_save_action',
+ 'weight' => '1',
+))
+->values(array(
+ 'hook' => 'nodeapi',
+ 'op' => 'presave',
+ 'aid' => 'node_make_sticky_action',
+ 'weight' => '1',
+))
+->values(array(
+ 'hook' => 'nodeapi',
+ 'op' => 'somehow_nodeapi_got_a_very_long',
+ 'aid' => 'node_save_action',
+ 'weight' => '1',
+))
+->execute();
+
+db_update('system')->fields(array(
+ 'schema_version' => '6000',
+ 'status' => '1',
+))
+->condition('filename', 'modules/trigger/trigger.module')
+->execute();
diff --git a/modules/simpletest/tests/upgrade/drupal-6.upload.database.php b/modules/simpletest/tests/upgrade/drupal-6.upload.database.php
index 493483f3d..c7f032ecb 100644
--- a/modules/simpletest/tests/upgrade/drupal-6.upload.database.php
+++ b/modules/simpletest/tests/upgrade/drupal-6.upload.database.php
@@ -114,6 +114,19 @@ db_insert('files')->fields(array(
'status' => '1',
'timestamp' => '1285708957',
))
+/*
+ * This is a case where the path is repeated twice.
+ */
+->values(array(
+ 'fid' => '11',
+ 'uid' => '1',
+ 'filename' => 'crazy-basename.png',
+ 'filepath' => '/drupal-6/file/directory/path/drupal-6/file/directory/path/crazy-basename.png',
+ 'filemime' => 'image/png',
+ 'filesize' => '329',
+ 'status' => '1',
+ 'timestamp' => '1285708958',
+))
->execute();
db_insert('node')->fields(array(
@@ -235,8 +248,8 @@ db_insert('node_revisions')->fields(array(
'vid' => '53',
'uid' => '1',
'title' => 'node title 40 revision 53',
- 'body' => "Attachments:\r\nforum-hot-new.png\r\nforum-hot.png\r\nforum-sticky.png\r\nforum-new.png",
- 'teaser' => "Attachments:\r\nforum-hot-new.png\r\nforum-hot.png\r\nforum-sticky.png\r\nforum-new.png",
+ 'body' => "Attachments:\r\nforum-hot-new.png\r\nforum-hot.png\r\nforum-sticky.png\r\nforum-new.png\r\ncrazy-basename.png",
+ 'teaser' => "Attachments:\r\nforum-hot-new.png\r\nforum-hot.png\r\nforum-sticky.png\r\nforum-new.png\r\ncrazy-basename.png",
'log' => '',
'timestamp' => '1285709012',
'format' => '1',
@@ -394,4 +407,12 @@ db_insert('upload')->fields(array(
'list' => '1',
'weight' => '-1',
))
+->values(array(
+ 'fid' => '11',
+ 'nid' => '40',
+ 'vid' => '53',
+ 'description' => 'crazy-basename.png',
+ 'list' => '1',
+ 'weight' => '0',
+))
->execute();
diff --git a/modules/simpletest/tests/upgrade/drupal-7.field.database.php b/modules/simpletest/tests/upgrade/drupal-7.field.database.php
new file mode 100644
index 000000000..630476133
--- /dev/null
+++ b/modules/simpletest/tests/upgrade/drupal-7.field.database.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+ * Test content for the field update path.
+ */
+
+db_insert('variable')->fields(array(
+ 'name',
+ 'value',
+))
+->values(array(
+ 'name' => 'field_bundle_settings',
+ 'value' => 'a:1:{s:4:"node";a:1:{s:4:"poll";a:1:{s:12:"extra_fields";a:1:{s:7:"display";a:2:{s:16:"poll_view_voting";a:1:{s:7:"default";a:2:{s:6:"weight";s:1:"0";s:7:"visible";b:1;}}s:17:"poll_view_results";a:1:{s:7:"default";a:2:{s:6:"weight";s:1:"0";s:7:"visible";b:0;}}}}}}}',
+))
+->execute();
diff --git a/modules/simpletest/tests/upgrade/drupal-7.trigger.database.php b/modules/simpletest/tests/upgrade/drupal-7.trigger.database.php
new file mode 100644
index 000000000..996f711dc
--- /dev/null
+++ b/modules/simpletest/tests/upgrade/drupal-7.trigger.database.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * @file
+ * Test content for the trigger upgrade path.
+ */
+
+// Add several trigger configurations.
+db_insert('trigger_assignments')->fields(array(
+ 'hook',
+ 'aid',
+ 'weight',
+))
+->values(array(
+ 'hook' => 'node_presave',
+ 'aid' => 'node_publish_action',
+ 'weight' => '1',
+))
+->values(array(
+ 'hook' => 'comment_presave',
+ 'aid' => 'comment_publish_action',
+ 'weight' => '1',
+))
+->values(array(
+ 'hook' => 'comment_delete',
+ 'aid' => 'node_save_action',
+ 'weight' => '1',
+))
+->execute();
diff --git a/modules/simpletest/tests/upgrade/update.field.test b/modules/simpletest/tests/upgrade/update.field.test
new file mode 100644
index 000000000..60d6ae8d9
--- /dev/null
+++ b/modules/simpletest/tests/upgrade/update.field.test
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * @file
+ * Provides update path tests for the Field module.
+ */
+
+/**
+ * Tests the Field 7.0 -> 7.x update path.
+ */
+class FieldUpdatePathTestCase extends UpdatePathTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Field update path',
+ 'description' => 'Field update path tests.',
+ 'group' => 'Upgrade path',
+ );
+ }
+
+ public function setUp() {
+ // Use the filled update path and our field data.
+ $path = drupal_get_path('module', 'simpletest') . '/tests/upgrade';
+ $this->databaseDumpFiles = array(
+ $path . '/drupal-7.filled.standard_all.database.php.gz',
+ $path . '/drupal-7.field.database.php',
+ );
+ parent::setUp();
+
+ // Our test data includes poll extra field settings.
+ $this->uninstallModulesExcept(array('field', 'poll'));
+ }
+
+ /**
+ * Tests that the update is successful.
+ */
+ public function testFilledUpgrade() {
+ $this->assertTrue($this->performUpgrade(), t('The update was completed successfully.'));
+ $expected_settings = array(
+ 'extra_fields' => array(
+ 'display' => array(
+ 'poll_view_voting' => array(
+ 'default' => array(
+ 'weight' => '0',
+ 'visible' => TRUE,
+ ),
+ ),
+ 'poll_view_results' => array(
+ 'default' => array(
+ 'weight' => '0',
+ 'visible' => FALSE,
+ ),
+ ),
+ ),
+ 'form' => array(),
+ ),
+ 'view_modes' => array(),
+ );
+ $actual_settings = field_bundle_settings('node', 'poll');
+ $this->assertEqual($expected_settings, $actual_settings, 'Settings stored in field_bundle_settings were updated to per-bundle settings.');
+ }
+}
diff --git a/modules/simpletest/tests/upgrade/update.trigger.test b/modules/simpletest/tests/upgrade/update.trigger.test
new file mode 100644
index 000000000..a91f7b9d8
--- /dev/null
+++ b/modules/simpletest/tests/upgrade/update.trigger.test
@@ -0,0 +1,37 @@
+<?php
+/**
+ * @file
+ * Provides upgrade path tests for the Trigger module.
+ */
+
+/**
+ * Tests the Trigger 7.0 -> 7.x upgrade path.
+ */
+class TriggerUpdatePathTestCase extends UpdatePathTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Trigger update path',
+ 'description' => 'Trigger update path tests.',
+ 'group' => 'Upgrade path',
+ );
+ }
+
+ public function setUp() {
+ // Use the filled upgrade path and our trigger data.
+ $this->databaseDumpFiles = array(
+ drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-7.filled.standard_all.database.php.gz',
+ drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-7.trigger.database.php',
+ );
+ parent::setUp();
+
+ // Our test data includes node and comment trigger assignments.
+ $this->uninstallModulesExcept(array('comment', 'trigger'));
+ }
+
+ /**
+ * Tests that the upgrade is successful.
+ */
+ public function testFilledUpgrade() {
+ $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+ }
+}
diff --git a/modules/simpletest/tests/upgrade/update.user.test b/modules/simpletest/tests/upgrade/update.user.test
new file mode 100644
index 000000000..4993139a4
--- /dev/null
+++ b/modules/simpletest/tests/upgrade/update.user.test
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Provides update path tests for the User module.
+ */
+
+/**
+ * Tests the User 7.0 -> 7.x update path.
+ */
+class UserUpdatePathTestCase extends UpdatePathTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'User update path',
+ 'description' => 'User update path tests.',
+ 'group' => 'Upgrade path',
+ );
+ }
+
+ public function setUp() {
+ // Use the filled update path and our field data.
+ $this->databaseDumpFiles = array(
+ drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-7.filled.standard_all.database.php.gz',
+ );
+ parent::setUp();
+ }
+
+ /**
+ * Tests that the update is successful.
+ */
+ public function testFilledUpgrade() {
+ $this->assertTrue($this->performUpgrade(), t('The update was completed successfully.'));
+ $this->assertTrue(db_index_exists('users', 'picture'), 'The {users}.picture column has an index.');
+ }
+}
diff --git a/modules/simpletest/tests/upgrade/upgrade.test b/modules/simpletest/tests/upgrade/upgrade.test
index 2602b09a2..172f30e69 100644
--- a/modules/simpletest/tests/upgrade/upgrade.test
+++ b/modules/simpletest/tests/upgrade/upgrade.test
@@ -549,7 +549,7 @@ class BasicStandardUpdatePath extends UpdatePathTestCase {
));
// Test that the site name is correctly displayed.
- $this->assertText('drupal', t('The site name is correctly displayed.'));
+ $this->assertText('Drupal', t('The site name is correctly displayed.'));
// Verify that the main admin sections are available.
$this->drupalGet('admin');
@@ -625,7 +625,7 @@ class BasicMinimalUpdatePath extends UpdatePathTestCase {
));
// Test that the site name is correctly displayed.
- $this->assertText('drupal', t('The site name is correctly displayed.'));
+ $this->assertText('Drupal', t('The site name is correctly displayed.'));
// Verify that the main admin sections are available.
$this->drupalGet('admin');
@@ -702,7 +702,7 @@ class FilledStandardUpdatePath extends UpdatePathTestCase {
));
// Test that the site name is correctly displayed.
- $this->assertText('drupal', t('The site name is correctly displayed.'));
+ $this->assertText('Drupal', t('The site name is correctly displayed.'));
// Verify that the main admin sections are available.
$this->drupalGet('admin');
@@ -778,7 +778,7 @@ class FilledMinimalUpdatePath extends UpdatePathTestCase {
));
// Test that the site name is correctly displayed.
- $this->assertText('drupal', t('The site name is correctly displayed.'));
+ $this->assertText('Drupal', t('The site name is correctly displayed.'));
// Verify that the main admin sections are available.
$this->drupalGet('admin');
diff --git a/modules/simpletest/tests/upgrade/upgrade.trigger.test b/modules/simpletest/tests/upgrade/upgrade.trigger.test
new file mode 100644
index 000000000..7413bed52
--- /dev/null
+++ b/modules/simpletest/tests/upgrade/upgrade.trigger.test
@@ -0,0 +1,39 @@
+<?php
+/**
+ * @file
+ * Provides upgrade path tests for the Trigger module.
+ */
+
+/**
+ * Tests the Trigger 6 -> 7 upgrade path.
+ */
+class UpgradePathTriggerTestCase extends UpgradePathTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Trigger upgrade path',
+ 'description' => 'Trigger upgrade path tests for Drupal 6.x.',
+ 'group' => 'Upgrade path',
+ );
+ }
+
+ public function setUp() {
+ // Path to the database dump.
+ $this->databaseDumpFiles = array(
+ drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.filled.database.php',
+ drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.trigger.database.php',
+ );
+ parent::setUp();
+ }
+
+ /**
+ * Basic tests for the trigger upgrade.
+ */
+ public function testTaxonomyUpgrade() {
+ $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+ $this->drupalGet('admin/structure/trigger/node');
+ $this->assertRaw('<td>'. t('Make post sticky') .'</td>');
+ $this->assertRaw('<td>'. t('Publish post') .'</td>');
+ $this->drupalGet('admin/structure/trigger/comment');
+ $this->assertRaw('<td>'. t('Publish comment') .'</td>');
+ }
+}
diff --git a/modules/simpletest/tests/upgrade/upgrade.upload.test b/modules/simpletest/tests/upgrade/upgrade.upload.test
index e3e1dc21e..276fae4e1 100644
--- a/modules/simpletest/tests/upgrade/upgrade.upload.test
+++ b/modules/simpletest/tests/upgrade/upgrade.upload.test
@@ -64,6 +64,12 @@ class UploadUpgradePathTestCase extends UpgradePathTestCase {
}
$this->assertIdentical($filenames, $recorded_filenames, 'The uploaded files are present in the same order after the upgrade.');
}
+ // Test for the file with repeating basename to only have the streaming
+ // path replaced.
+ $node = node_load(40, 53);
+ $repeated_basename_file = $node->upload[LANGUAGE_NONE][4];
+ $this->assertEqual($repeated_basename_file['uri'], 'private://drupal-6/file/directory/path/crazy-basename.png', "The file with the repeated basename path only had the stream portion replaced");
+
// Make sure the file settings were properly migrated.
$d6_file_directory_temp = '/drupal-6/file/directory/temp';
$d6_file_directory_path = '/drupal-6/file/directory/path';