diff options
Diffstat (limited to 'modules/simpletest/tests')
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'; |