';
- $context['message'] .= theme('item_list', $items);
-
- // Save working values for the next iteration.
- $context['sandbox']['tests'] = $test_list;
- $context['sandbox']['test_results'] = $test_results;
- // The test_id is the only thing we need to save for the report page.
- $context['results']['test_id'] = $test_id;
-
- // Multistep processing: report progress.
- $context['finished'] = 1 - $size / $max;
-}
-
-function _simpletest_batch_finished($success, $results, $operations, $elapsed) {
- if ($success) {
- drupal_set_message(t('The test run finished in @elapsed.', array('@elapsed' => $elapsed)));
- }
- else {
- // Use the test_id passed as a parameter to _simpletest_batch_operation().
- $test_id = $operations[0][1][1];
-
- // Retrieve the last database prefix used for testing and the last test
- // class that was run from. Use the information to read the lgo file
- // in case any fatal errors caused the test to crash.
- list($last_prefix, $last_test_class) = simpletest_last_test_get($test_id);
- simpletest_log_read($test_id, $last_prefix, $last_test_class);
-
-
- drupal_set_message(t('The test run did not successfully finish.'), 'error');
- drupal_set_message(t('Please use the Clean environment button to clean-up temporary files and tables.'), 'warning');
- }
- module_invoke_all('test_group_finished');
-}
-
/*
* Get information about the last test that ran given a test ID.
*
@@ -300,76 +233,6 @@
}
/**
- * Get a list of all of the tests provided by the system.
- *
- * The list of test classes is loaded from the registry where it looks for
- * files ending in ".test". Once loaded the test list is cached and stored in
- * a static variable. In order to list tests provided by disabled modules
- * hook_registry_files_alter() is used to forcefully add them to the registry.
- *
- * @return
- * An array of tests keyed with the groups specified in each of the tests
- * getInfo() method and then keyed by the test class. An example of the array
- * structure is provided below.
- *
- * @code
- * $groups['Blog'] => array(
- * 'BlogTestCase' => array(
- * 'name' => 'Blog functionality',
- * 'description' => 'Create, view, edit, delete, ...',
- * 'group' => 'Blog',
- * ),
- * );
- * @endcode
- * @see simpletest_registry_files_alter()
- */
-function simpletest_test_get_all() {
- $groups = &drupal_static(__FUNCTION__);
-
- if (!$groups) {
- // Load test information from cache if available, otherwise retrieve the
- // information from each tests getInfo() method.
- if ($cache = cache_get('simpletest', 'cache')) {
- $groups = $cache->data;
- }
- else {
- // Select all clases in files ending with .test.
- $classes = db_select('registry')
- ->fields('registry', array('name'))
- ->condition('type', 'class')
- ->condition('filename', '%.test', 'LIKE')
- ->execute();
-
- $groups = array();
-
- // Check that each class has a getInfo() method and store the information
- // in an array keyed with the group specified in the test information.
- foreach ($classes as $class) {
- $class = $class->name;
- if (class_exists($class) && method_exists($class, 'getInfo')) {
- // Valid test class, retrieve test information.
- $info = call_user_func(array($class, 'getInfo'));
-
- // Initialize test groups.
- if (!isset($groups[$info['group']])) {
- $groups[$info['group']] = array();
- }
- $groups[$info['group']][$class] = $info;
- }
- }
- // Sort the groups and tests within the groups by name.
- uksort($groups, 'strnatcasecmp');
- foreach ($groups as $group => &$tests) {
- uksort($tests, 'strnatcasecmp');
- }
-
- cache_set('simpletest', $groups);
- }
- }
- return $groups;
-}
-
-/**
* Implementation of hook_registry_files_alter().
*
* Add the test files for disabled modules so that we get a list containing
Index: modules/simpletest/simpletest.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/simpletest.pages.inc,v
retrieving revision 1.16
diff -u -r1.16 simpletest.pages.inc
--- modules/simpletest/simpletest.pages.inc 11 Sep 2009 01:53:29 -0000 1.16
+++ modules/simpletest/simpletest.pages.inc 11 Sep 2009 20:17:25 -0000
@@ -7,414 +7,6 @@
*/
/**
- * List tests arranged in groups that can be selected and run.
- */
-function simpletest_test_form() {
- $form = array();
-
- $form['tests'] = array(
- '#type' => 'fieldset',
- '#title' => t('Tests'),
- '#description' => t('Select the test(s) or test group(s) you would like to run, and click Run tests.'),
- );
-
- $form['tests']['table'] = array(
- '#theme' => 'simpletest_test_table',
- );
-
- // Generate the list of tests arranged by group.
- $groups = simpletest_test_get_all();
- foreach ($groups as $group => $tests) {
- $form['tests']['table'][$group] = array(
- '#collapsed' => TRUE,
- );
-
- foreach ($tests as $class => $info) {
- $form['tests']['table'][$group][$class] = array(
- '#type' => 'checkbox',
- '#title' => $info['name'],
- '#description' => $info['description'],
- );
- }
- }
-
- // Operation buttons.
- $form['tests']['op'] = array(
- '#type' => 'submit',
- '#value' => t('Run tests'),
- );
- $form['clean'] = array(
- '#type' => 'fieldset',
- '#collapsible' => FALSE,
- '#collapsed' => FALSE,
- '#title' => t('Clean test environment'),
- '#description' => t('Remove tables with the prefix "simpletest" and temporary directories that are left over from tests that crashed. This is intended for developers when creating tests.'),
- );
- $form['clean']['op'] = array(
- '#type' => 'submit',
- '#value' => t('Clean environment'),
- '#submit' => array('simpletest_clean_environment'),
- );
-
- return $form;
-}
-
-/**
- * Theme the test list generated by simpletest_test_form() into a table.
- *
- * @param $table Form array that represent a table.
- * @return HTML output.
- */
-function theme_simpletest_test_table($table) {
- drupal_add_css(drupal_get_path('module', 'simpletest') . '/simpletest.css');
- drupal_add_js(drupal_get_path('module', 'simpletest') . '/simpletest.js');
-
- // Create header for test selection table.
- $header = array(
- theme('table_select_header_cell'),
- array('data' => t('Test'), 'class' => array('simpletest_test')),
- array('data' => t('Description'), 'class' => array('simpletest_description')),
- );
-
- // Define the images used to expand/collapse the test groups.
- $js = array(
- 'images' => array(
- theme('image', 'misc/menu-collapsed.png', 'Expand', 'Expand'),
- theme('image', 'misc/menu-expanded.png', 'Collapsed', 'Collapsed'),
- ),
- );
-
- // Cycle through each test group and create a row.
- $rows = array();
- foreach (element_children($table) as $key) {
- $element = &$table[$key];
- $row = array();
-
- // Make the class name safe for output on the page by replacing all
- // non-word/decimal characters with a dash (-).
- $test_class = strtolower(trim(preg_replace("/[^\w\d]/", "-", $key)));
-
- // Select the right "expand"/"collapse" image, depending on whether the
- // category is expanded (at least one test selected) or not.
- $collapsed = !empty($element['#collapsed']);
- $image_index = $collapsed ? 0 : 1;
-
- // Place-holder for checkboxes to select group of tests.
- $row[] = array('id' => $test_class, 'class' => array('simpletest-select-all'));
-
- // Expand/collapse image and group title.
- $row[] = array(
- 'data' => ' ' .
- '',
- 'style' => 'font-weight: bold;'
- );
-
- $row[] = ' ';
-
- $rows[] = array('data' => $row, 'class' => array('simpletest-group'));
-
- // Add individual tests to group.
- $current_js = array(
- 'testClass' => $test_class . '-test',
- 'testNames' => array(),
- 'imageDirection' => $image_index,
- 'clickActive' => FALSE,
- );
-
- // Sorting $element by children's #title attribute instead of by class name.
- uasort($element, '_simpletest_sort_by_title');
-
- // Cycle through each test within the current group.
- foreach (element_children($element) as $test_name) {
- $test = $element[$test_name];
- $row = array();
-
- $current_js['testNames'][] = 'edit-' . $test_name;
-
- // Store test title and description so that checkbox won't render them.
- $title = $test['#title'];
- $description = $test['#description'];
-
- unset($test['#title']);
- unset($test['#description']);
-
- // Test name is used to determine what tests to run.
- $test['#name'] = $test_name;
-
- $row[] = drupal_render($test);
- $row[] = theme('indentation', 1) . '';
- $row[] = '
' . $description . '
';
-
- $rows[] = array('data' => $row, 'class' => array($test_class . '-test', ($collapsed ? 'js-hide' : '')));
- }
- $js['simpletest-test-group-' . $test_class] = $current_js;
- unset($table[$key]);
- }
-
- // Add js array of settings.
- drupal_add_js(array('simpleTest' => $js), 'setting');
-
- if (empty($rows)) {
- return '' . t('No tests to display.') . '';
- }
- else {
- return theme('table', $header, $rows, array('id' => 'simpletest-form-table'));
- }
-}
-
-/**
- * Sort element by title instead of by class name.
- */
-function _simpletest_sort_by_title($a, $b) {
- // This is for parts of $element that are not an array.
- if (!isset($a['#title']) || !isset($b['#title'])) {
- return 1;
- }
-
- return strcasecmp($a['#title'], $b['#title']);
-}
-
-/**
- * Run selected tests.
- */
-function simpletest_test_form_submit($form, &$form_state) {
- // Get list of tests.
- $tests_list = array();
- foreach ($form_state['values'] as $class_name => $value) {
- if (class_exists($class_name) && $value === 1) {
- $tests_list[] = $class_name;
- }
- }
- if (count($tests_list) > 0 ) {
- simpletest_run_tests($tests_list, 'drupal');
- }
- else {
- drupal_set_message(t('No test(s) selected.'), 'error');
- }
-}
-
-/**
- * Test results form for $test_id.
- */
-function simpletest_result_form(&$form_state, $test_id) {
- $form = array();
-
- // Make sure there are test results to display and a re-run is not being performed.
- $results = array();
- if (is_numeric($test_id) && !$results = simpletest_result_get($test_id)) {
- drupal_set_message(t('No test results to display.'), 'error');
- drupal_goto('admin/config/development/testing');
- return $form;
- }
-
- // Load all classes and include CSS.
- drupal_add_css(drupal_get_path('module', 'simpletest') . '/simpletest.css');
-
- // Keep track of which test cases passed or failed.
- $filter = array(
- 'pass' => array(),
- 'fail' => array(),
- );
-
- // Summary result fieldset.
- $form['result'] = array(
- '#type' => 'fieldset',
- '#title' => t('Results'),
- );
- $form['result']['summary'] = $summary = array(
- '#theme' => 'simpletest_result_summary',
- '#pass' => 0,
- '#fail' => 0,
- '#exception' => 0,
- '#debug' => 0,
- );
-
- // Cycle through each test group.
- $header = array(t('Message'), t('Group'), t('Filename'), t('Line'), t('Function'), array('colspan' => 2, 'data' => t('Status')));
- $form['result']['results'] = array();
- foreach ($results as $group => $assertions) {
- // Create group fieldset with summary information.
- $info = call_user_func(array($group, 'getInfo'));
- $form['result']['results'][$group] = array(
- '#type' => 'fieldset',
- '#title' => $info['name'],
- '#description' => $info['description'],
- '#collapsible' => TRUE,
- );
- $form['result']['results'][$group]['summary'] = $summary;
- $group_summary = &$form['result']['results'][$group]['summary'];
-
- // Create table of assertions for the group.
- $rows = array();
- foreach ($assertions as $assertion) {
- $row = array();
- $row[] = $assertion->message;
- $row[] = $assertion->message_group;
- $row[] = basename($assertion->file);
- $row[] = $assertion->line;
- $row[] = $assertion->function;
- $row[] = simpletest_result_status_image($assertion->status);
-
- $class = 'simpletest-' . $assertion->status;
- if ($assertion->message_group == 'Debug') {
- $class = 'simpletest-debug';
- }
- $rows[] = array('data' => $row, 'class' => array($class));
-
- $group_summary['#' . $assertion->status]++;
- $form['result']['summary']['#' . $assertion->status]++;
- }
- $form['result']['results'][$group]['table'] = array(
- '#theme' => 'table',
- '#header' => $header,
- '#rows' => $rows,
- );
-
- // Set summary information.
- $group_summary['#ok'] = $group_summary['#fail'] + $group_summary['#exception'] == 0;
- $form['result']['results'][$group]['#collapsed'] = $group_summary['#ok'] && !$group_summary['#debug'];
-
- // Store test group (class) as for use in filter.
- $filter[$group_summary['#ok'] ? 'pass' : 'fail'][] = $group;
- }
-
- // Overal summary status.
- $form['result']['summary']['#ok'] = $form['result']['summary']['#fail'] + $form['result']['summary']['#exception'] == 0;
-
- // Actions.
- $form['#action'] = url('admin/config/development/testing/results/re-run');
- $form['action'] = array(
- '#type' => 'fieldset',
- '#title' => t('Actions'),
- '#attributes' => array('class' => array('container-inline')),
- '#weight' => -11,
- );
-
- $form['action']['filter'] = array(
- '#type' => 'select',
- '#title' => 'Filter',
- '#options' => array(
- 'all' => t('All (@count)', array('@count' => count($filter['pass']) + count($filter['fail']))),
- 'pass' => t('Pass (@count)', array('@count' => count($filter['pass']))),
- 'fail' => t('Fail (@count)', array('@count' => count($filter['fail']))),
- ),
- );
- $form['action']['filter']['#default_value'] = ($filter['fail'] ? 'fail' : 'all');
-
- // Catagorized test classes for to be used with selected filter value.
- $form['action']['filter_pass'] = array(
- '#type' => 'hidden',
- '#default_value' => implode(',', $filter['pass']),
- );
- $form['action']['filter_fail'] = array(
- '#type' => 'hidden',
- '#default_value' => implode(',', $filter['fail']),
- );
-
- $form['action']['op'] = array(
- '#type' => 'submit',
- '#value' => t('Run tests'),
- );
-
- $form['action']['return'] = array(
- '#markup' => l(t('Return to list'), 'admin/config/development/testing'),
- );
-
- if (is_numeric($test_id)) {
- simpletest_clean_results_table($test_id);
- }
-
- return $form;
-}
-
-/**
- * Re-run the tests that match the filter.
- */
-function simpletest_result_form_submit($form, &$form_state) {
- $pass = $form_state['values']['filter_pass'] ? explode(',', $form_state['values']['filter_pass']) : array();
- $fail = $form_state['values']['filter_fail'] ? explode(',', $form_state['values']['filter_fail']) : array();
-
- if ($form_state['values']['filter'] == 'all') {
- $classes = array_merge($pass, $fail);
- }
- else if ($form_state['values']['filter'] == 'pass') {
- $classes = $pass;
- }
- else {
- $classes = $fail;
- }
-
- if (!$classes) {
- $form_state['redirect'] = 'admin/config/development/testing';
- return;
- }
-
- $form_state_execute = array('values' => array());
- foreach ($classes as $class) {
- $form_state_execute['values'][$class] = 1;
- }
-
- simpletest_test_form_submit(array(), $form_state_execute);
-}
-
-/**
- * Add wrapper div with class based on summary status.
- *
- * @return HTML output.
- */
-function theme_simpletest_result_summary($form) {
- return '
' . _simpletest_format_summary_line($form) . '
';
-}
-
-/**
- * Get test results for $test_id.
- *
- * @param $test_id The test_id to retrieve results of.
- * @return Array of results grouped by test_class.
- */
-function simpletest_result_get($test_id) {
- $results = db_select('simpletest')
- ->fields('simpletest')
- ->condition('test_id', $test_id)
- ->orderBy('test_class')
- ->orderBy('message_id')
- ->execute();
-
- $test_results = array();
- foreach ($results as $result) {
- if (!isset($test_results[$result->test_class])) {
- $test_results[$result->test_class] = array();
- }
- $test_results[$result->test_class][] = $result;
- }
- return $test_results;
-}
-
-/**
- * Get the appropriate image for the status.
- *
- * @param $status Status string, either: pass, fail, exception.
- * @return HTML image or false.
- */
-function simpletest_result_status_image($status) {
- // $map does not use drupal_static() as its value never changes.
- static $map;
-
- if (!isset($map)) {
- $map = array(
- 'pass' => theme('image', 'misc/watchdog-ok.png', t('Pass')),
- 'fail' => theme('image', 'misc/watchdog-error.png', t('Fail')),
- 'exception' => theme('image', 'misc/watchdog-warning.png', t('Exception')),
- 'debug' => theme('image', 'misc/watchdog-warning.png', t('Debug')),
- );
- }
- if (isset($map[$status])) {
- return $map[$status];
- }
- return FALSE;
-}
-
-/**
* Provides settings form for SimpleTest variables.
*/
function simpletest_settings_form(&$form_state) {
Index: modules/simpletest/simpletest.js.inc
===================================================================
RCS file: modules/simpletest/simpletest.js.inc
diff -N modules/simpletest/simpletest.js.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ modules/simpletest/simpletest.js.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,173 @@
+ $_SESSION['test_class']), 'setting');
+ $form_state = array();
+ return simpletest_test_form($form_state, simpletest_js_get_all());
+}
+
+/**
+ * Ensure that at least one tests is selected.
+ */
+function simpletest_js_form_validate($form, &$form_state) {
+ $valid = FALSE;
+ foreach ($form_state['values'] as $class_name => $value) {
+ if ($value === 1) {
+ $valid = TRUE;
+ }
+ }
+
+ if ($form_state['clicked_button']['#value'] == t('Run tests') && !$valid) {
+ form_set_error('op', t('No test(s) selected.'));
+ }
+}
+
+/**
+ * Initiate batch process to run selected tests.
+ */
+function simpletest_js_form_submit($form, &$form_state) {
+ $tests = array();
+ foreach ($form_state['values'] as $class_name => $value) {
+ if ($value === 1) {
+ $tests[] = $class_name;
+ }
+ }
+
+ simpletest_test_run('js', $tests);
+}
+
+/**
+ * Get a list of all of the JS tests provided by the system.
+ *
+ * If tests are not cached the goto simpletest/js/collect where javascript will
+ * be invoked that will send back all test information to the server.
+ *
+ * @see simpletest_php_get_all()
+ */
+function simpletest_js_get_all() {
+ $groups = &drupal_static(__FUNCTION__, array());
+
+ if (!$groups) {
+ if ($cache = cache_get('simpletest_js', 'cache')) {
+ $groups = $cache->data;
+ }
+ else {
+ drupal_goto('simpletest/js/collect');
+ }
+ }
+
+ return $groups;
+}
+
+/**
+ * Collect the list of JS tests.
+ */
+function simpletest_js_collect() {
+ // TODO Temporary.
+ $groups = array();
+ $groups['System'] = array(
+ 'checkPlain' => array(
+ 'name' => 'Check plain',
+ 'description' => 'Tests the Drupal.checkPlain() JavaScript function for properly escaping HTML.',
+ 'group' => 'System',
+ ),
+ 't' => array(
+ 'name' => 'Translation',
+ 'description' => 'Tests the basic translation functionality of the Drupal.t() function, including the proper handling of variable strings.',
+ 'group' => 'System',
+ ),
+ 'behaviors' => array(
+ 'name' => 'JavaScript behaviors',
+ 'description' => 'Tests the functionality of Drupal behaviors to make sure it allows JavaScript files to attach and detach behaviors in different contexts.',
+ 'group' => 'System',
+ ),
+ );
+ cache_set('simpletest_js', $groups);
+
+ drupal_goto('admin/config/development/testing/js');
+}
+
+/**
+ * Callback that registers javascript tests.
+ */
+function simpletest_js_register() {
+ $groups = array();
+ if ($cache = cache_get('simpletest_js', 'cache')) {
+ $groups = $cache->data;
+ }
+
+ // TODO Add new data.
+
+ // Sort the groups by key and the individual tests by name.
+ uksort($groups, 'strnatcasecmp');
+ foreach ($groups as $group => &$tests) {
+ uksort($tests, 'simpletest_sort_by_name');
+ }
+
+ cache_set('simpletest_js', $groups);
+}
+
+/**
+ * Set up the QUnit testing framework.
+ */
+function simpletest_js_qunit() {
+ drupal_add_library('simpletest', 'qunit');
+ $directories = simpletest_js_tests_load();
+
+ drupal_add_js(array('modules' => $directories), 'setting');
+ drupal_add_js(array('activeTest' => $_SESSION['test_class']), 'setting');
+
+ echo theme('simpletest_qunit', drupal_get_js(), drupal_get_css());
+}
+
+/**
+ * Load all the JS tests provided.
+ *
+ * @return
+ * List of directories in which the tests reside.
+ */
+function simpletest_js_tests_load() {
+ $directories = array();
+ foreach (_system_get_module_data() as $module => $info) {
+ $found = FALSE;
+ $directory = dirname($info->uri);
+
+ $file = "$directory/$module.test.js";
+ if (is_file($file)) {
+ drupal_add_js($file);
+ $found = TRUE;
+ }
+
+ if (is_dir("$directory/tests")) {
+ foreach (file_scan_directory("$directory/tests", '/\.test\.js$/') as $file) {
+ drupal_add_js($file->uri);
+ $found = TRUE;
+ }
+ }
+
+ if ($found) {
+ $directories[$module] = $directory;
+ }
+ }
+
+ return $directories;
+}
+
+/**
+ * Record test results from javascript test.
+ */
+function simpletest_js_record() {
+ foreach ($_POST['assertions'] as $assertion) {
+ $status = $assertion['status'] == 'true' ? 'pass' : 'fail';
+ DrupalTestCase::insertAssert($_SESSION['test_id'], $_POST['index'], $status, $assertion['message']);
+ }
+}
Index: modules/simpletest/tests/drupal.test.js
===================================================================
RCS file: modules/simpletest/tests/drupal.test.js
diff -N modules/simpletest/tests/drupal.test.js
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ modules/simpletest/tests/drupal.test.js 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,136 @@
+// $Id: drupal.test.js,v 1.3 2009/09/04 09:42:20 cwgordon7 Exp $
+
+(function($) {
+
+/**
+ * Test the Drupal.checkPlain function.
+ */
+Drupal.tests.checkPlain = {
+ getInfo: function() {
+ return {
+ name: 'Check plain',
+ description: 'Tests the Drupal.checkPlain() JavaScript function for properly escaping HTML.',
+ group: 'System'
+ };
+ },
+ test: function() {
+ expect(9);
+
+ // Test basic strings.
+ equals(Drupal.checkPlain('test'), 'test', Drupal.t("Nothing gets replaced that doesn't need to be replaced with their escaped equivalent."));
+ equals(Drupal.checkPlain('"test'), '"test', Drupal.t('Quotes are replaced with their escaped equivalent.'));
+ equals(Drupal.checkPlain('Test&1'), 'Test&1', Drupal.t('Ampersands are replaced with their escaped equivalent.'));
+ equals(Drupal.checkPlain('Test>test'), 'Test>test', Drupal.t('Greater-than signs are replaced with their escaped equivalent.'));
+ equals(Drupal.checkPlain('TestStuff'), '<tagname property="value">Stuff</tagname>', Drupal.t('Full HTML tags are replaced with their escaped equivalent.'));
+ equals(Drupal.checkPlain('Test "&".'), 'Test "&".', Drupal.t('A string with both quotes and ampersands replaces those entities with their escaped equivalents.'));
+ }
+};
+
+/**
+ * Tests Drupal.t().
+ */
+Drupal.tests.t = {
+ getInfo: function() {
+ return {
+ name: 'Translation',
+ description: 'Tests the basic translation functionality of the Drupal.t() function, including the proper handling of variable strings.',
+ group: 'System'
+ };
+ },
+ setup: function() {
+ this.originalLocale = Drupal.locale;
+ Drupal.locale = {
+ 'strings': {
+ 'Translation 1': '1 noitalsnarT',
+ 'Translation with a @placeholder': '@placeholder a with Translation',
+ 'Translation with another %placeholder': '%placeholder in another translation',
+ 'Literal !placeholder': 'A literal !placeholder',
+ 'Test unspecified placeholder': 'Unspecified placeholder test'
+ }
+ };
+ },
+ teardown: function() {
+ Drupal.locale = this.originalLocale;
+ },
+ test: function() {
+ expect(9);
+
+ var html = 'Apples & Oranges';
+ var escaped = '<tag attribute="value">Apples & Oranges</tag>';
+
+ // Test placeholders.
+ equals(Drupal.t('Hello world! @html', {'@html': html}), 'Hello world! ' + escaped, Drupal.t('The "@" placeholder escapes the variable.'));
+ equals(Drupal.t('Hello world! %html', {'%html': html}), 'Hello world! ' + escaped + '', Drupal.t('The "%" placeholder escapes the variable and themes it as a placeholder.'));
+ equals(Drupal.t('Hello world! !html', {'!html': html}), 'Hello world! ' + html, Drupal.t('The "!" placeholder passes the variable through as-is.'));
+ equals(Drupal.t('Hello world! html', {'html': html}), 'Hello world! ' + escaped + '', Drupal.t('Other placeholders act as "%" placeholders do.'));
+
+ // Test actual translations.
+ equals(Drupal.t('Translation 1'), '1 noitalsnarT', Drupal.t('Basic translations work.'));
+ equals(Drupal.t('Translation with a @placeholder', {'@placeholder': ''}), '<script>alert("xss")</script> a with Translation', Drupal.t('Translations with the "@" placeholder work.'));
+ equals(Drupal.t('Translation with another %placeholder', {'%placeholder': ''}), '<script>alert("xss")</script> in another translation', Drupal.t('Translations with the "%" placeholder work.'));
+ equals(Drupal.t('Literal !placeholder', {'!placeholder': ''}), 'A literal ', Drupal.t('Translations with the "!" placeholder work.'));
+ equals(Drupal.t('Test unspecified placeholder', {'placeholder': ''}), 'Unspecified <script>alert("xss")</script> test', Drupal.t('Translations with unspecified placeholders work.'));
+ },
+};
+
+/**
+ * Tests Drupal.attachBehaviors() and Drupal.detachBehaviors().
+ */
+Drupal.tests.behaviors = {
+ getInfo: function() {
+ return {
+ name: 'JavaScript behaviors',
+ description: 'Tests the functionality of Drupal behaviors to make sure it allows JavaScript files to attach and detach behaviors in different contexts.',
+ group: 'System'
+ };
+ },
+ setup: function() {
+ this.originalBehaviors = Drupal.behaviors;
+ var attachIndex = 0;
+ var detachIndex = 0;
+ Drupal.behaviors = {
+ testBehavior: {
+ attach: function(context, settings) {
+ attachIndex++;
+ equals(context, 'Attach context ' + attachIndex, Drupal.t('Attach context matches passed context.'));
+ equals(settings, 'Attach settings ' + attachIndex, Drupal.t('Attach settings match passed settings.'));
+ },
+ detach: function(context, settings) {
+ detachIndex++;
+ equals(context, 'Detach context ' + detachIndex, Drupal.t('Detach context matches passed context.'));
+ equals(settings, 'Detach settings ' + detachIndex, Drupal.t('Detach settings match passed settings.'));
+ }
+ }
+ };
+ },
+ teardown: function() {
+ Drupal.behaviors = this.originalBehaviors;
+ },
+ test: function() {
+ expect(8);
+
+ // Test attaching behaviors.
+ Drupal.attachBehaviors('Attach context 1', 'Attach settings 1');
+
+ // Test attaching behaviors again.
+ Drupal.attachBehaviors('Attach context 2', 'Attach settings 2');
+
+ // Test detaching behaviors.
+ Drupal.detachBehaviors('Detach context 1', 'Detach settings 1');
+
+ // Try detaching behaviors again.
+ Drupal.detachBehaviors('Detach context 2', 'Detach settings 2');
+ },
+ teardown: function() {
+ Drupal.behaviors = this.originalBehaviors;
+ }
+};
+
+})(jQuery);
Index: modules/simpletest/simpletest.php.inc
===================================================================
RCS file: modules/simpletest/simpletest.php.inc
diff -N modules/simpletest/simpletest.php.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ modules/simpletest/simpletest.php.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,120 @@
+ $value) {
+ if ($value === 1 && !class_exists($class_name)) {
+ form_set_error($class_name, t('%class is not a valid test class.', array('%class' => $class_name)));
+ }
+ elseif ($value === 1) {
+ $valid = TRUE;
+ }
+ }
+
+ if ($form_state['clicked_button']['#value'] == t('Run tests') && !$valid) {
+ form_set_error('op', t('No test(s) selected.'));
+ }
+}
+
+/**
+ * Initiate batch process to run selected tests.
+ */
+function simpletest_php_form_submit($form, &$form_state) {
+ $tests = array();
+ foreach ($form_state['values'] as $class_name => $value) {
+ if ($value === 1) {
+ $tests[] = $class_name;
+ }
+ }
+
+ simpletest_test_run('php', $tests);
+}
+
+/**
+ * Get a list of all of the PHP tests provided by the system.
+ *
+ * The list of test classes is loaded from the registry where it looks for
+ * files ending in ".test". Once loaded the test list is cached and stored in
+ * a static variable. In order to list tests provided by disabled modules
+ * hook_registry_files_alter() is used to forcefully add them to the registry.
+ *
+ * @return
+ * An array of tests keyed with the groups specified in each of the tests
+ * getInfo() method and then keyed by the test class. An example of the array
+ * structure is provided below.
+ *
+ * @code
+ * $groups['Blog'] => array(
+ * 'BlogTestCase' => array(
+ * 'name' => 'Blog functionality',
+ * 'description' => 'Create, view, edit, delete, ...',
+ * 'group' => 'Blog',
+ * ),
+ * );
+ * @endcode
+ * @see simpletest_registry_files_alter()
+ */
+function simpletest_php_get_all() {
+ $groups = &drupal_static(__FUNCTION__);
+
+ if (!$groups) {
+ // Load test information from cache if available, otherwise retrieve the
+ // information from each tests getInfo() method.
+ if ($cache = cache_get('simpletest_php', 'cache')) {
+ $groups = $cache->data;
+ }
+ else {
+ // Select all clases in files ending with .test.
+ $classes = db_select('registry')
+ ->fields('registry', array('name'))
+ ->condition('type', 'class')
+ ->condition('filename', '%.test', 'LIKE')
+ ->execute();
+
+ $groups = array();
+
+ // Check that each class has a getInfo() method and store the information
+ // in an array keyed with the group specified in the test information.
+ foreach ($classes as $class) {
+ $class = $class->name;
+ if (class_exists($class) && method_exists($class, 'getInfo')) {
+ // Valid test class, retrieve test information.
+ $info = call_user_func(array($class, 'getInfo'));
+
+ // Initialize test groups.
+ if (!isset($groups[$info['group']])) {
+ $groups[$info['group']] = array();
+ }
+ $groups[$info['group']][$class] = $info;
+ }
+ }
+
+ // Sort the groups by key and the individual tests by name.
+ uksort($groups, 'strnatcasecmp');
+ foreach ($groups as $group => &$tests) {
+ uksort($tests, 'simpletest_sort_by_name');
+ }
+
+ cache_set('simpletest_php', $groups);
+ }
+ }
+ return $groups;
+}
Index: modules/simpletest/simpletest.inc
===================================================================
RCS file: modules/simpletest/simpletest.inc
diff -N modules/simpletest/simpletest.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ modules/simpletest/simpletest.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,616 @@
+ 'fieldset',
+ '#title' => t('Tests'),
+ '#description' => t('Select the test(s) or test group(s) you would like to run, and click Run tests.'),
+ );
+ $form['tests']['table'] = array(
+ '#theme' => 'simpletest_test_table',
+ );
+
+ // Generate the list of tests arranged by group.
+ foreach ($groups as $group => $tests) {
+ if (!isset($form['tests']['table'][$group])) {
+ $form['tests']['table'][$group] = array(
+ '#collapsed' => TRUE,
+ );
+ }
+
+ foreach ($tests as $key => $info) {
+ $form['tests']['table'][$group][$key] = array(
+ '#type' => 'checkbox',
+ '#title' => $info['name'],
+ '#description' => $info['description'],
+ );
+ }
+ }
+
+ // Operation buttons.
+ $form['tests']['op'] = array(
+ '#type' => 'submit',
+ '#value' => t('Run tests'),
+ );
+ $form['clean'] = array(
+ '#type' => 'fieldset',
+ '#collapsible' => FALSE,
+ '#collapsed' => FALSE,
+ '#title' => t('Clean test environment'),
+ '#description' => t('Remove tables with the prefix "simpletest" and temporary directories that are left over from tests that crashed. This is intended for developers when creating tests.'),
+ );
+ $form['clean']['op'] = array(
+ '#type' => 'submit',
+ '#value' => t('Clean environment'),
+ '#submit' => array('simpletest_clean_environment'),
+ );
+
+ return $form;
+}
+
+/**
+ * Theme the test list generated by simpletest_test_form() into a table.
+ *
+ * @param $table Form array that represent a table.
+ * @return HTML output.
+ */
+function theme_simpletest_test_table($table) {
+ drupal_add_css(drupal_get_path('module', 'simpletest') . '/simpletest.css');
+ drupal_add_js(drupal_get_path('module', 'simpletest') . '/simpletest.js');
+
+ // Create header for test selection table.
+ $header = array(
+ theme('table_select_header_cell'),
+ array('data' => t('Test'), 'class' => array('simpletest_test')),
+ array('data' => t('Description'), 'class' => array('simpletest_description')),
+ );
+
+ // Define the images used to expand/collapse the test groups.
+ $js = array(
+ 'images' => array(
+ theme('image', 'misc/menu-collapsed.png', 'Expand', 'Expand'),
+ theme('image', 'misc/menu-expanded.png', 'Collapsed', 'Collapsed'),
+ ),
+ );
+
+ // Cycle through each test group and create a row.
+ $rows = array();
+ foreach (element_children($table) as $key) {
+ $element = &$table[$key];
+ $row = array();
+
+ // Make the class name safe for output on the page by replacing all
+ // non-word/decimal characters with a dash (-).
+ $test_class = strtolower(trim(preg_replace("/[^\w\d]/", "-", $key)));
+
+ // Select the right "expand"/"collapse" image, depending on whether the
+ // category is expanded (at least one test selected) or not.
+ $collapsed = !empty($element['#collapsed']);
+ $image_index = $collapsed ? 0 : 1;
+
+ // Place-holder for checkboxes to select group of tests.
+ $row[] = array('id' => $test_class, 'class' => array('simpletest-select-all'));
+
+ // Expand/collapse image and group title.
+ $row[] = array(
+ 'data' => ' ' .
+ '',
+ 'style' => 'font-weight: bold;'
+ );
+
+ $row[] = ' ';
+
+ $rows[] = array('data' => $row, 'class' => array('simpletest-group'));
+
+ // Add individual tests to group.
+ $current_js = array(
+ 'testClass' => $test_class . '-test',
+ 'testNames' => array(),
+ 'imageDirection' => $image_index,
+ 'clickActive' => FALSE,
+ );
+
+ // Cycle through each test within the current group.
+ foreach (element_children($element) as $test_name) {
+ $test = $element[$test_name];
+ $row = array();
+
+ $current_js['testNames'][] = 'edit-' . $test_name;
+
+ // Store test title and description so that checkbox won't render them.
+ $title = $test['#title'];
+ $description = $test['#description'];
+
+ unset($test['#title']);
+ unset($test['#description']);
+
+ // Test name is used to determine what tests to run.
+ $test['#name'] = $test_name;
+
+ $row[] = drupal_render($test);
+ $row[] = theme('indentation', 1) . '';
+ $row[] = '