Commit a4f6e550 authored by catch's avatar catch
Browse files

Issue #3110862 by longwave, alexpott, catch, Mile23, Lendude, Gábor Hojtsy,...

Issue #3110862 by longwave, alexpott, catch, Mile23, Lendude, Gábor Hojtsy, Berdir: Remove simpletest module from core
parent f2c6af66
......@@ -602,7 +602,6 @@
"drupal/settings_tray": "self.version",
"drupal/seven": "self.version",
"drupal/shortcut": "self.version",
"drupal/simpletest": "self.version",
"drupal/standard": "self.version",
"drupal/stark": "self.version",
"drupal/statistics": "self.version",
......@@ -4099,9 +4098,6 @@
"ext-zip": "Enabling the zip extension allows you to unzip archives",
"ext-zlib": "Allow gzip compression of HTTP requests"
},
"bin": [
"bin/composer"
],
"type": "library",
"extra": {
"branch-alias": {
......
......@@ -148,7 +148,6 @@
"drupal/settings_tray": "self.version",
"drupal/seven": "self.version",
"drupal/shortcut": "self.version",
"drupal/simpletest": "self.version",
"drupal/standard": "self.version",
"drupal/stark": "self.version",
"drupal/statistics": "self.version",
......
......@@ -4,6 +4,7 @@
use Drupal\Core\DrupalKernel;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\ExtensionDiscovery;
use Drupal\Core\Site\Settings;
use Symfony\Component\HttpFoundation\Request;
......@@ -35,12 +36,17 @@ public function __construct($environment, $class_loader, $allow_dumping = FALSE,
// DateFormatter::formatInterval() cause a plugin not found exception.
$this->moduleList = [
'system' => 0,
'simpletest' => 0,
];
$this->moduleData = [
'system' => new Extension($this->root, 'module', 'core/modules/system/system.info.yml', 'system.module'),
'simpletest' => new Extension($this->root, 'module', 'core/modules/simpletest/simpletest.info.yml', 'simpletest.module'),
];
// In order to support Simpletest in Drupal 9 conditionally include the
// module.
$extensions = (new ExtensionDiscovery($this->root, FALSE, [], 'ignore_site_path_does_not_exist'))->scan('module', FALSE);
if (isset($extensions['simpletest'])) {
$this->moduleList['simpletest'] = 0;
$this->moduleData['simpletest'] = $extensions['simpletest'];
}
}
/**
......
......@@ -72,7 +72,6 @@ class StateFileExists extends MigrateDrupalTestBase {
'rdf',
'search',
'shortcut',
'simpletest',
'statistics',
'syslog',
'system',
......
clear_results: true
httpauth:
method: 1
password: ''
username: ''
verbose: true
# Schema for the configuration files of the Simpletest module.
simpletest.settings:
type: config_object
label: 'Testing'
mapping:
clear_results:
type: boolean
label: 'Clear results after each complete test suite run'
verbose:
type: boolean
label: 'Provide verbose information when running tests'
httpauth:
type: mapping
label: 'HTTP authentication'
mapping:
method:
type: integer
label: 'Method'
username:
type: string
label: 'Username'
password:
type: string
label: 'Password'
/* Test Table */
#simpletest-form-table th.select-all {
width: 1em;
}
th.simpletest-test-label {
width: 40%;
}
.simpletest-image {
display: inline-block;
width: 1em;
cursor: pointer;
}
.simpletest-group-label label {
display: inline;
font-weight: bold;
}
.simpletest-test-label label {
margin-left: 1em; /* LTR */
}
.simpletest-test-description .description {
margin: 0;
}
#simpletest-form-table tr td {
color: #494949;
background-color: white;
}
#simpletest-form-table tr.simpletest-group td {
color: #494949;
background-color: #edf5fa;
}
table#simpletest-form-table tr.simpletest-group label {
display: inline;
}
div.message > div.item-list {
font-weight: normal;
}
div.simpletest-pass {
color: #33a333;
}
.simpletest-fail {
color: #981010;
}
tr.simpletest-pass,
tr.simpletest-pass.odd {
background-color: #b6ffb6;
}
tr.simpletest-pass.even {
background-color: #9bff9b;
}
tr.simpletest-fail,
tr.simpletest-fail.odd {
background-color: #ffc9c9;
}
tr.simpletest-fail.even {
background-color: #ffacac;
}
tr.simpletest-exception,
tr.simpletest-exception.odd {
background-color: #f4ea71;
}
tr.simpletest-exception.even {
background-color: #f5e742;
}
tr.simpletest-debug,
tr.simpletest-debug.odd {
background-color: #eee;
}
tr.simpletest-debug.even {
background-color: #fff;
}
a.simpletest-collapse {
position: absolute;
top: -99em;
width: 0;
height: 0;
}
a.simpletest-collapse:focus,
a.simpletest-collapse:hover {
position: relative;
z-index: 1000;
top: 0;
overflow: visible;
width: auto;
height: auto;
font-size: 80%;
}
id: d6_simpletest_settings
label: Simpletest configuration
migration_tags:
- Drupal 6
- Configuration
source:
plugin: variable
variables:
- simpletest_clear_results
- simpletest_httpauth_method
- simpletest_httpauth_password
- simpletest_httpauth_username
- simpletest_verbose
source_module: simpletest
process:
clear_results: simpletest_clear_results
'httpauth/method': simpletest_httpauth_method
'httpauth/password': simpletest_httpauth_password
'httpauth/username': simpletest_httpauth_username
verbose: simpletest_verbose
destination:
plugin: config
config_name: simpletest.settings
id: d7_simpletest_settings
label: SimpleTest configuration
migration_tags:
- Drupal 7
- Configuration
source:
plugin: variable
variables:
- simpletest_clear_results
- simpletest_httpauth_method
- simpletest_httpauth_password
- simpletest_httpauth_username
- simpletest_verbose
source_module: simpletest
process:
clear_results: simpletest_clear_results
'httpauth/method': simpletest_httpauth_method
'httpauth/password': simpletest_httpauth_password
'httpauth/username': simpletest_httpauth_username
verbose: simpletest_verbose
destination:
plugin: config
config_name: simpletest.settings
finished:
6:
simpletest: simpletest
7:
simpletest: simpletest
<?php
/**
* @file
* Hooks provided by the SimpleTest module.
*/
/**
* @addtogroup hooks
* @{
*/
/**
* Alter the list of tests.
*
* This hook will not be invoked by the phpunit tool.
*
* @param $groups
* A two dimensional array, the first key is the test group, the second is the
* name of the test class, and the value is in associative array containing
* 'name', 'description', 'group', and 'requires' keys.
*
* @deprecated in drupal:8.6.0 and is removed from drupal:9.0.0. Convert
* your test to a PHPUnit-based one and implement test listeners.
*
* @see https://www.drupal.org/node/2939892
*/
function hook_simpletest_alter(&$groups) {
// An alternative session handler module would not want to run the original
// Session HTTPS handling test because it checks the sessions table in the
// database.
unset($groups['Session']['testHttpsSession']);
}
/**
* A test group has started.
*
* This hook is called just once at the beginning of a test group.
*
* This hook is only invoked by the Simpletest UI form runner. It will not be
* invoked by run-tests.sh or the phpunit tool.
*
* @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Convert your
* test to a PHPUnit-based one and implement test listeners.
*
* @see https://www.drupal.org/node/2934242
*/
function hook_test_group_started() {
}
/**
* A test group has finished.
*
* This hook is called just once at the end of a test group.
*
* This hook is only invoked by the Simpletest UI form runner. It will not be
* invoked by run-tests.sh or the phpunit tool.
*
* @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Convert your
* test to a PHPUnit-based one and implement test listeners.
*
* @see https://www.drupal.org/node/2934242
*/
function hook_test_group_finished() {
}
/**
* An individual test has finished.
*
* This hook is called when an individual test has finished.
*
* This hook is only invoked by the Simpletest UI form runner. It will not be
* invoked by run-tests.sh or the phpunit tool.
*
* @param
* $results The results of the test as gathered by
* \Drupal\simpletest\WebTestBase.
*
* @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Convert your
* test to a PHPUnit-based one and implement test listeners.
*
* @see https://www.drupal.org/node/2934242
* @see _simpletest_batch_operation()
*/
function hook_test_finished($results) {
}
/**
* @} End of "addtogroup hooks".
*/
/**
* @file
* Simpletest behaviors.
*/
(function($, Drupal, drupalSettings) {
/**
* Collapses table rows followed by group rows on the test listing page.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attach collapse behavior on the test listing page.
*/
Drupal.behaviors.simpleTestGroupCollapse = {
attach(context) {
$(context)
.find('.simpletest-group')
.once('simpletest-group-collapse')
.each(function() {
const $group = $(this);
const $image = $group.find('.simpletest-image');
$image.html(drupalSettings.simpleTest.images[0]).on('click', () => {
const $tests = $group.nextUntil('.simpletest-group');
const expand = !$group.hasClass('expanded');
$group.toggleClass('expanded', expand);
$tests.toggleClass('js-hide', !expand);
$image.html(drupalSettings.simpleTest.images[+expand]);
});
});
},
};
/**
* Toggles test checkboxes to match the group checkbox.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches behavior for selecting all tests in a group.
*/
Drupal.behaviors.simpleTestSelectAll = {
attach(context) {
$(context)
.find('.simpletest-group')
.once('simpletest-group-select-all')
.each(function() {
const $group = $(this);
const $cell = $group.find('.simpletest-group-select-all');
const $groupCheckbox = $(Drupal.theme('checkbox')).attr(
'id',
`${$cell.attr('id')}-group-select-all`,
);
const $testCheckboxes = $group
.nextUntil('.simpletest-group')
.find('input[type=checkbox]');
$cell.append($groupCheckbox);
// Toggle the test checkboxes when the group checkbox is toggled.
$groupCheckbox.on('change', function() {
const checked = $(this).prop('checked');
$testCheckboxes.prop('checked', checked);
});
// Update the group checkbox when a test checkbox is toggled.
function updateGroupCheckbox() {
let allChecked = true;
$testCheckboxes.each(function() {
if (!$(this).prop('checked')) {
allChecked = false;
return false;
}
});
$groupCheckbox.prop('checked', allChecked);
}
$testCheckboxes.on('change', updateGroupCheckbox);
});
},
};
/**
* Filters the test list table by a text input search string.
*
* Text search input: input.table-filter-text
* Target table: input.table-filter-text[data-table]
* Source text: .table-filter-text-source
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the filter behavior to the text input element.
*/
Drupal.behaviors.simpletestTableFilterByText = {
attach(context) {
const $input = $('input.table-filter-text').once('table-filter-text');
const $table = $($input.attr('data-table'));
let $rows;
let searched = false;
function filterTestList(e) {
const query = $(e.target)
.val()
.toLowerCase();
function showTestRow(index, row) {
const $row = $(row);
const $sources = $row.find('.table-filter-text-source');
const textMatch =
$sources
.text()
.toLowerCase()
.indexOf(query) !== -1;
$row.closest('tr').toggle(textMatch);
}
// Filter if the length of the query is at least 3 characters.
if (query.length >= 3) {
// Indicate that a search has been performed, and hide the
// "select all" checkbox.
searched = true;
$('#simpletest-form-table thead th.select-all input').hide();
$rows.each(showTestRow);
}
// Restore to the original state if any searching has occurred.
else if (searched) {
searched = false;
$('#simpletest-form-table thead th.select-all input').show();
// Restore all rows to their original display state.
$rows.css('display', '');
}
}
if ($table.length) {
$rows = $table.find('tbody tr');
$input
.trigger('focus')
.on('keyup', Drupal.debounce(filterTestList, 200));
}
},
};
})(jQuery, Drupal, drupalSettings);
name: Testing
type: module
description: 'Provides a framework for unit and functional testing.'
description: 'Deprecated. SimpleTest has been removed from core.'
package: Core
version: VERSION
configure: simpletest.settings
hidden: true
......@@ -2,85 +2,13 @@
/**
* @file
* Install, update and uninstall functions for the simpletest module.
* Uninstall functions for the simpletest module.
*/
use Drupal\Component\FileSecurity\FileSecurity;
use Drupal\Component\Utility\Environment;
use Drupal\Core\Database\Database;
use Drupal\Core\File\Exception\FileException;
use Drupal\Core\Test\TestDatabase;
use PHPUnit\Framework\TestCase;
/**
* Minimum value of PHP memory_limit for SimpleTest.
*/
const SIMPLETEST_MINIMUM_PHP_MEMORY_LIMIT = '128M';
/**
* Implements hook_requirements().
*/
function simpletest_requirements($phase) {
$requirements = [];
$requirements['deprecation'] = [
'title' => t('Testing (SimpleTest)'),
'value' => t('The <em>Testing</em> (SimpleTest) module is deprecated for removal in Drupal 9. It should not be enabled on production sites. Read <a href="https://www.drupal.org/node/3091784">The Drupal core SimpleTest module is deprecated</a> for alternative ways to run tests during development.'),
'severity' => $phase === 'runtime' ? REQUIREMENT_WARNING : REQUIREMENT_INFO,
];
$has_phpunit = class_exists(TestCase::class);
$has_curl = function_exists('curl_init');
$requirements['phpunit'] = [
'title' => t('PHPUnit dependency'),
'value' => $has_phpunit ? t('Found') : t('Not found'),
];
if (!$has_phpunit) {
$requirements['phpunit']['severity'] = REQUIREMENT_ERROR;
$requirements['phpunit']['description'] = t("The testing framework requires the PHPUnit package. Please run 'composer install' to ensure it is present.");
}
$requirements['curl'] = [
'title' => t('cURL'),
'value' => $has_curl ? t('Enabled') : t('Not found'),
];
if (!$has_curl) {
$requirements['curl']['severity'] = REQUIREMENT_ERROR;
$requirements['curl']['description'] = t('The testing framework requires the <a href="https://secure.php.net/manual/en/curl.setup.php">PHP cURL library</a>. For more information, see the <a href="https://www.drupal.org/requirements/php/curl">online information on installing the PHP cURL extension</a>.');
}
// Check the current memory limit. If it is set too low, SimpleTest will fail
// to load all tests and throw a fatal error.
$memory_limit = ini_get('memory_limit');
if (!Environment::checkMemoryLimit(SIMPLETEST_MINIMUM_PHP_MEMORY_LIMIT, $memory_limit)) {
$requirements['php_memory_limit']['severity'] = REQUIREMENT_WARNING;
$requirements['php_memory_limit']['description'] = t('The testing framework requires the PHP memory limit to be at least %memory_minimum_limit. The current value is %memory_limit. <a href=":url">Follow these steps to continue</a>.', ['%memory_limit' => $memory_limit, '%memory_minimum_limit' => SIMPLETEST_MINIMUM_PHP_MEMORY_LIMIT, ':url' => 'https://www.drupal.org/node/207036']);
}
$site_directory = 'sites/simpletest';
if (!drupal_verify_install_file(\Drupal::root() . '/' . $site_directory, FILE_EXIST | FILE_READABLE | FILE_WRITABLE | FILE_EXECUTABLE, 'dir')) {
$requirements['simpletest_site_directory'] = [
'title' => t('Simpletest site directory'),
'value' => is_dir(\Drupal::root() . '/' . $site_directory) ? t('Not writable') : t('Missing'),
'severity' => REQUIREMENT_ERROR,
'description' => t('The testing framework requires the %sites-simpletest directory to exist and be writable in order to run tests.', [
'%sites-simpletest' => $site_directory,
]),
];
}
elseif (!FileSecurity::writeHtaccess(\Drupal::root() . '/' . $site_directory, FALSE)) {
$requirements['simpletest_site_directory'] = [
'title' => t('Simpletest site directory'),
'value' => t('Not protected'),
'severity' => REQUIREMENT_ERROR,
'description' => t('The file %file does not exist and could not be created automatically, which poses a security risk. Ensure that the directory is writable.', [
'%file' => $site_directory . '/.htaccess',
]),
];
}
return $requirements;
}
use Symfony\Component\Console\Output\NullOutput;
/**
* Implements hook_schema().
......@@ -94,11 +22,25 @@ function simpletest_schema() {
*/
function simpletest_uninstall() {
// Do not clean the environment in case the Simpletest module is uninstalled
// in a (recursive) test for itself, since simpletest_clean_environment()
// would also delete the test site of the parent test process.
// in a (recursive) test for itself, since EnvironmentCleaner would also
// delete the test site of the parent test process.
if (!drupal_valid_test_ua()) {
\Drupal::service('environment_cleaner')->cleanEnvironment();
// Clean up left-over tables and directories.
$cleaner = new EnvironmentCleaner(
DRUPAL_ROOT,
Database::getConnection(),
TestDatabase::getConnection(),
new NullOutput(),
\Drupal::service('file_system')
);
try {
$cleaner->cleanEnvironment();
}
catch (Exception $e) {