Update to Drupal 8.0.0 beta 14. For more information, see https://drupal.org/node/2544542
This commit is contained in:
parent
3b2511d96d
commit
81ccda77eb
2155 changed files with 54307 additions and 46870 deletions
|
@ -0,0 +1,21 @@
|
|||
id: d6_simpletest_settings
|
||||
label: Drupal 6 simpletest configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- simpletest_clear_results
|
||||
- simpletest_httpauth_method
|
||||
- simpletest_httpauth_password
|
||||
- simpletest_httpauth_username
|
||||
- simpletest_verbose
|
||||
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
|
|
@ -487,41 +487,47 @@ function simpletest_classloader_register() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Generates test file.
|
||||
* Generates a test file.
|
||||
*
|
||||
* @param string $filename
|
||||
* The name of the file, including the path.
|
||||
* The name of the file, including the path. The suffix '.txt' is appended to
|
||||
* the supplied file name and the file is put into the public:// files
|
||||
* directory.
|
||||
* @param int $width
|
||||
* The number of characters on one line.
|
||||
* @param int $lines
|
||||
* The number of lines in the file.
|
||||
* @param string $type
|
||||
* (optional) The type, for example: "text", "binary", or "binary-text".
|
||||
* (optional) The type, one of:
|
||||
* - text: The generated file contains random ASCII characters.
|
||||
* - binary: The generated file contains random characters whose codes are in
|
||||
* the range of 0 to 31.
|
||||
* - binary-text: The generated file contains random sequence of '0' and '1'
|
||||
* values.
|
||||
*
|
||||
* @return string
|
||||
* The name of the file, including the path.
|
||||
*/
|
||||
function simpletest_generate_file($filename, $width, $lines, $type = 'binary-text') {
|
||||
$size = $width * $lines - $lines;
|
||||
|
||||
// Generate random text
|
||||
$text = '';
|
||||
for ($i = 0; $i < $size; $i++) {
|
||||
switch ($type) {
|
||||
case 'text':
|
||||
$text .= chr(rand(32, 126));
|
||||
break;
|
||||
case 'binary':
|
||||
$text .= chr(rand(0, 31));
|
||||
break;
|
||||
case 'binary-text':
|
||||
default:
|
||||
$text .= rand(0, 1);
|
||||
break;
|
||||
for ($i = 0; $i < $lines; $i++) {
|
||||
// Generate $width - 1 characters to leave space for the "\n" character.
|
||||
for ($j = 0; $j < $width - 1; $j++) {
|
||||
switch ($type) {
|
||||
case 'text':
|
||||
$text .= chr(rand(32, 126));
|
||||
break;
|
||||
case 'binary':
|
||||
$text .= chr(rand(0, 31));
|
||||
break;
|
||||
case 'binary-text':
|
||||
default:
|
||||
$text .= rand(0, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$text .= "\n";
|
||||
}
|
||||
}
|
||||
// Add \n for symmetrical file.
|
||||
$text = wordwrap($text, $width - 1, "\n", TRUE) . "\n";
|
||||
|
||||
// Create filename.
|
||||
file_put_contents('public://' . $filename . '.txt', $text);
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace Drupal\simpletest;
|
|||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Utility\Xss;
|
||||
use Drupal\Core\Render\RenderContext;
|
||||
use Symfony\Component\CssSelector\CssSelector;
|
||||
|
||||
/**
|
||||
|
@ -397,7 +398,7 @@ trait AssertContentTrait {
|
|||
if (!$message) {
|
||||
$message = SafeMarkup::format('Raw "@raw" found', array('@raw' => $raw));
|
||||
}
|
||||
return $this->assert(strpos($this->getRawContent(), $raw) !== FALSE, $message, $group);
|
||||
return $this->assert(strpos($this->getRawContent(), (string) $raw) !== FALSE, $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -424,7 +425,7 @@ trait AssertContentTrait {
|
|||
if (!$message) {
|
||||
$message = SafeMarkup::format('Raw "@raw" not found', array('@raw' => $raw));
|
||||
}
|
||||
return $this->assert(strpos($this->getRawContent(), $raw) === FALSE, $message, $group);
|
||||
return $this->assert(strpos($this->getRawContent(), (string) $raw) === FALSE, $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -808,7 +809,12 @@ trait AssertContentTrait {
|
|||
* TRUE on pass, FALSE on fail.
|
||||
*/
|
||||
protected function assertThemeOutput($callback, array $variables = array(), $expected = '', $message = '', $group = 'Other') {
|
||||
$output = \Drupal::theme()->render($callback, $variables);
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = \Drupal::service('renderer');
|
||||
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function() use ($callback, $variables) {
|
||||
return \Drupal::theme()->render($callback, $variables);
|
||||
});
|
||||
$this->verbose(
|
||||
'<hr />' . 'Result:' . '<pre>' . SafeMarkup::checkPlain(var_export($output, TRUE)) . '</pre>'
|
||||
. '<hr />' . 'Expected:' . '<pre>' . SafeMarkup::checkPlain(var_export($expected, TRUE)) . '</pre>'
|
||||
|
|
|
@ -950,7 +950,7 @@ abstract class BrowserTestBase extends \PHPUnit_Framework_TestCase {
|
|||
// Reset/rebuild all data structures after enabling the modules, primarily
|
||||
// to synchronize all data structures and caches between the test runner and
|
||||
// the child site.
|
||||
// Affects e.g. file_get_stream_wrappers().
|
||||
// Affects e.g. StreamWrapperManagerInterface::getWrappers().
|
||||
// @see \Drupal\Core\DrupalKernel::bootCode()
|
||||
// @todo Test-specific setUp() methods may set up further fixtures; find a
|
||||
// way to execute this after setUp() is done, or to eliminate it entirely.
|
||||
|
|
|
@ -313,7 +313,7 @@ class SimpletestResultsForm extends FormBase {
|
|||
$rows = array();
|
||||
foreach ($assertions as $assertion) {
|
||||
$row = array();
|
||||
$row[] = SafeMarkup::checkAdminXss($assertion->message);
|
||||
$row[] = ['data' => ['#markup' => $assertion->message]];
|
||||
$row[] = $assertion->message_group;
|
||||
$row[] = \Drupal::service('file_system')->basename(($assertion->file));
|
||||
$row[] = $assertion->line;
|
||||
|
|
|
@ -127,8 +127,8 @@ class SimpletestTestForm extends FormBase {
|
|||
'#suffix' => '<a href="#" class="simpletest-collapse">(' . $this->t('Collapse') . ')</a>',
|
||||
);
|
||||
$form['tests']['#attached']['drupalSettings']['simpleTest']['images'] = [
|
||||
$this->renderer->renderPlain($image_collapsed),
|
||||
$this->renderer->renderPlain($image_extended),
|
||||
(string) $this->renderer->renderPlain($image_collapsed),
|
||||
(string) $this->renderer->renderPlain($image_extended),
|
||||
];
|
||||
|
||||
// Generate the list of tests arranged by group.
|
||||
|
|
|
@ -381,9 +381,7 @@ EOD;
|
|||
protected function installConfig(array $modules) {
|
||||
foreach ($modules as $module) {
|
||||
if (!$this->container->get('module_handler')->moduleExists($module)) {
|
||||
throw new \RuntimeException(format_string("'@module' module is not enabled.", array(
|
||||
'@module' => $module,
|
||||
)));
|
||||
throw new \RuntimeException("'$module' module is not enabled");
|
||||
}
|
||||
\Drupal::service('config.installer')->installDefaultConfig('module', $module);
|
||||
}
|
||||
|
@ -411,18 +409,13 @@ EOD;
|
|||
// behavior and non-reproducible test failures, we only allow the schema of
|
||||
// explicitly loaded/enabled modules to be installed.
|
||||
if (!$this->container->get('module_handler')->moduleExists($module)) {
|
||||
throw new \RuntimeException(format_string("'@module' module is not enabled.", array(
|
||||
'@module' => $module,
|
||||
)));
|
||||
throw new \RuntimeException("'$module' module is not enabled");
|
||||
}
|
||||
$tables = (array) $tables;
|
||||
foreach ($tables as $table) {
|
||||
$schema = drupal_get_module_schema($module, $table);
|
||||
if (empty($schema)) {
|
||||
throw new \RuntimeException(format_string("Unknown '@table' table schema in '@module' module.", array(
|
||||
'@module' => $module,
|
||||
'@table' => $table,
|
||||
)));
|
||||
throw new \RuntimeException("Unknown '$table' table schema in '$module' module.");
|
||||
}
|
||||
$this->container->get('database')->schema()->createTable($table, $schema);
|
||||
}
|
||||
|
|
|
@ -1423,9 +1423,9 @@ abstract class TestBase {
|
|||
* Do not use this method when special characters are not possible (e.g., in
|
||||
* machine or file names that have already been validated); instead, use
|
||||
* \Drupal\simpletest\TestBase::randomMachineName(). If $length is greater
|
||||
* than 2 the random string will include at least one ampersand ('&')
|
||||
* character to ensure coverage for special characters and avoid the
|
||||
* introduction of random test failures.
|
||||
* than 3 the random string will include at least one ampersand ('&') and
|
||||
* at least one greater than ('>') character to ensure coverage for special
|
||||
* characters and avoid the introduction of random test failures.
|
||||
*
|
||||
* @param int $length
|
||||
* Length of random string to generate.
|
||||
|
@ -1436,7 +1436,7 @@ abstract class TestBase {
|
|||
* @see \Drupal\Component\Utility\Random::string()
|
||||
*/
|
||||
public function randomString($length = 8) {
|
||||
if ($length < 3) {
|
||||
if ($length < 4) {
|
||||
return $this->getRandomGenerator()->string($length, TRUE, array($this, 'randomStringValidate'));
|
||||
}
|
||||
|
||||
|
@ -1444,9 +1444,10 @@ abstract class TestBase {
|
|||
// returned string contains a character that needs to be escaped in HTML by
|
||||
// injecting an ampersand into it.
|
||||
$replacement_pos = floor($length / 2);
|
||||
// Remove 1 from the length to account for the ampersand character.
|
||||
$string = $this->getRandomGenerator()->string($length - 1, TRUE, array($this, 'randomStringValidate'));
|
||||
return substr_replace($string, '&', $replacement_pos, 0);
|
||||
// Remove 2 from the length to account for the ampersand and greater than
|
||||
// characters.
|
||||
$string = $this->getRandomGenerator()->string($length - 2, TRUE, array($this, 'randomStringValidate'));
|
||||
return substr_replace($string, '>&', $replacement_pos, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\simpletest\Tests\Migrate\d6\MigrateSimpletestConfigsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\simpletest\Tests\Migrate\d6;
|
||||
|
||||
use Drupal\config\Tests\SchemaCheckTestTrait;
|
||||
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* Upgrade variables to simpletest.settings.yml.
|
||||
*
|
||||
* @group simpletest
|
||||
*/
|
||||
class MigrateSimpletestConfigsTest extends MigrateDrupal6TestBase {
|
||||
|
||||
use SchemaCheckTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('simpletest');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installConfig(['simpletest']);
|
||||
$this->loadDumps(['Variable.php']);
|
||||
$this->executeMigration('d6_simpletest_settings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests migration of simpletest variables to simpletest.settings.yml.
|
||||
*/
|
||||
public function testSimpletestSettings() {
|
||||
$config = $this->config('simpletest.settings');
|
||||
$this->assertIdentical(TRUE, $config->get('clear_results'));
|
||||
$this->assertIdentical(CURLAUTH_BASIC, $config->get('httpauth.method'));
|
||||
// NULL in the dump means defaults which is empty string. Same as omitting
|
||||
// them.
|
||||
$this->assertIdentical('', $config->get('httpauth.password'));
|
||||
$this->assertIdentical('', $config->get('httpauth.username'));
|
||||
$this->assertIdentical(TRUE, $config->get('verbose'));
|
||||
$this->assertConfigSchema(\Drupal::service('config.typed'), 'simpletest.settings', $config->get());
|
||||
}
|
||||
|
||||
}
|
|
@ -124,6 +124,8 @@ class SimpleTestBrowserTest extends WebTestBase {
|
|||
* Tests that PHPUnit and KernelTestBase tests work through the UI.
|
||||
*/
|
||||
public function testTestingThroughUI() {
|
||||
$this->drupalGet('admin/config/development/testing');
|
||||
$this->assertTrue(strpos($this->drupalSettings['simpleTest']['images'][0], 'core/misc/menu-collapsed.png') > 0, 'drupalSettings contains a link to core/misc/menu-collapsed.png.');
|
||||
// We can not test WebTestBase tests here since they require a valid .htkey
|
||||
// to be created. However this scenario is covered by the testception of
|
||||
// \Drupal\simpletest\Tests\SimpleTestTest.
|
||||
|
|
|
@ -157,7 +157,7 @@ EOD;
|
|||
// request. This allows the stub test to make requests. The event does not
|
||||
// fire here and drupal_generate_test_ua() can not generate a key for a
|
||||
// test in a test since the prefix has changed.
|
||||
// @see \Drupal\Core\Test\EventSubscriber\HttpRequestSubscriber::onBeforeSendRequest()
|
||||
// @see \Drupal\Core\Test\HttpClientMiddleware\TestHttpClientMiddleware::onBeforeSendRequest()
|
||||
// @see drupal_generate_test_ua();
|
||||
$key_file = DRUPAL_ROOT . '/sites/simpletest/' . substr($this->databasePrefix, 10) . '/.htkey';
|
||||
$private_key = Crypt::randomBytesBase64(55);
|
||||
|
|
|
@ -32,6 +32,7 @@ use Drupal\Core\Url;
|
|||
use Drupal\node\Entity\NodeType;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Zend\Diactoros\Uri;
|
||||
|
||||
/**
|
||||
* Test case for typical Drupal tests.
|
||||
|
@ -457,16 +458,37 @@ abstract class WebTestBase extends TestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets a list files that can be used in tests.
|
||||
* Gets a list of files that can be used in tests.
|
||||
*
|
||||
* The first time this method is called, it will call
|
||||
* simpletest_generate_file() to generate binary and ASCII text files in the
|
||||
* public:// directory. It will also copy all files in
|
||||
* core/modules/simpletest/files to public://. These contain image, SQL, PHP,
|
||||
* JavaScript, and HTML files.
|
||||
*
|
||||
* All filenames are prefixed with their type and have appropriate extensions:
|
||||
* - text-*.txt
|
||||
* - binary-*.txt
|
||||
* - html-*.html and html-*.txt
|
||||
* - image-*.png, image-*.jpg, and image-*.gif
|
||||
* - javascript-*.txt and javascript-*.script
|
||||
* - php-*.txt and php-*.php
|
||||
* - sql-*.txt and sql-*.sql
|
||||
*
|
||||
* Any subsequent calls will not generate any new files, or copy the files
|
||||
* over again. However, if a test class adds a new file to public:// that
|
||||
* is prefixed with one of the above types, it will get returned as well, even
|
||||
* on subsequent calls.
|
||||
*
|
||||
* @param $type
|
||||
* File type, possible values: 'binary', 'html', 'image', 'javascript',
|
||||
* 'php', 'sql', 'text'.
|
||||
* @param $size
|
||||
* File size in bytes to match. Please check the tests/files folder.
|
||||
* (optional) File size in bytes to match. Defaults to NULL, which will not
|
||||
* filter the returned list by size.
|
||||
*
|
||||
* @return
|
||||
* List of files that match filter.
|
||||
* List of files in public:// that match the filter(s).
|
||||
*/
|
||||
protected function drupalGetTestFiles($type, $size = NULL) {
|
||||
if (empty($this->generatedTestFiles)) {
|
||||
|
@ -477,11 +499,11 @@ abstract class WebTestBase extends TestBase {
|
|||
simpletest_generate_file('binary-' . $count++, 64, $line, 'binary');
|
||||
}
|
||||
|
||||
// Generate text test files.
|
||||
// Generate ASCII text test files.
|
||||
$lines = array(16, 256, 1024, 2048, 20480);
|
||||
$count = 0;
|
||||
foreach ($lines as $line) {
|
||||
simpletest_generate_file('text-' . $count++, 64, $line);
|
||||
simpletest_generate_file('text-' . $count++, 64, $line, 'text');
|
||||
}
|
||||
|
||||
// Copy other test files from simpletest.
|
||||
|
@ -1533,7 +1555,15 @@ abstract class WebTestBase extends TestBase {
|
|||
if (!isset($options['query'][MainContentViewSubscriber::WRAPPER_FORMAT])) {
|
||||
$options['query'][MainContentViewSubscriber::WRAPPER_FORMAT] = 'drupal_ajax';
|
||||
}
|
||||
return Json::decode($this->drupalGet($path, $options, $headers));
|
||||
return Json::decode($this->drupalGetXHR($path, $options, $headers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a Drupal path as if it is a XMLHttpRequest.
|
||||
*/
|
||||
protected function drupalGetXHR($path, array $options = array(), array $headers = array()) {
|
||||
$headers[] = 'X-Requested-With: XMLHttpRequest';
|
||||
return $this->drupalGet($path, $options, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1591,17 +1621,14 @@ abstract class WebTestBase extends TestBase {
|
|||
*
|
||||
* This function can also be called to emulate an Ajax submission. In this
|
||||
* case, this value needs to be an array with the following keys:
|
||||
* - path: A path to submit the form values to for Ajax-specific processing,
|
||||
* which is likely different than the $path parameter used for retrieving
|
||||
* the initial form. Defaults to 'system/ajax'.
|
||||
* - triggering_element: If the value for the 'path' key is 'system/ajax' or
|
||||
* another generic Ajax processing path, this needs to be set to the name
|
||||
* of the element. If the name doesn't identify the element uniquely, then
|
||||
* this should instead be an array with a single key/value pair,
|
||||
* corresponding to the element name and value. The callback for the
|
||||
* generic Ajax processing path uses this to find the #ajax information
|
||||
* for the element, including which specific callback to use for
|
||||
* processing the request.
|
||||
* - path: A path to submit the form values to for Ajax-specific processing.
|
||||
* - triggering_element: If the value for the 'path' key is a generic Ajax
|
||||
* processing path, this needs to be set to the name of the element. If
|
||||
* the name doesn't identify the element uniquely, then this should
|
||||
* instead be an array with a single key/value pair, corresponding to the
|
||||
* element name and value. The \Drupal\Core\Form\FormAjaxResponseBuilder
|
||||
* uses this to find the #ajax information for the element, including
|
||||
* which specific callback to use for processing the request.
|
||||
*
|
||||
* This can also be set to NULL in order to emulate an Internet Explorer
|
||||
* submission of a form with a single text field, and pressing ENTER in that
|
||||
|
@ -1649,7 +1676,10 @@ abstract class WebTestBase extends TestBase {
|
|||
$submit_matches = $this->handleForm($post, $edit, $upload, $ajax ? NULL : $submit, $form);
|
||||
$action = isset($form['action']) ? $this->getAbsoluteUrl((string) $form['action']) : $this->getUrl();
|
||||
if ($ajax) {
|
||||
$action = $this->getAbsoluteUrl(!empty($submit['path']) ? $submit['path'] : 'system/ajax');
|
||||
if (empty($submit['path'])) {
|
||||
throw new \Exception('No #ajax path specified.');
|
||||
}
|
||||
$action = $this->getAbsoluteUrl($submit['path']);
|
||||
// Ajax callbacks verify the triggering element if necessary, so while
|
||||
// we may eventually want extra code that verifies it in the
|
||||
// handleForm() function, it's not currently a requirement.
|
||||
|
@ -1661,16 +1691,20 @@ abstract class WebTestBase extends TestBase {
|
|||
$post_array = $post;
|
||||
if ($upload) {
|
||||
foreach ($upload as $key => $file) {
|
||||
$file = drupal_realpath($file);
|
||||
if ($file && is_file($file)) {
|
||||
// Use the new CurlFile class for file uploads when using PHP
|
||||
// 5.5.
|
||||
if (class_exists('CurlFile')) {
|
||||
$post[$key] = curl_file_create($file);
|
||||
if (is_array($file) && count($file)) {
|
||||
// There seems to be no way via php's API to cURL to upload
|
||||
// several files with the same post field name. However, Drupal
|
||||
// still sees array-index syntax in a similar way.
|
||||
for ($i = 0; $i < count($file); $i++) {
|
||||
$postfield = str_replace('[]', '', $key) . '[' . $i . ']';
|
||||
$file_path = $this->container->get('file_system')->realpath($file[$i]);
|
||||
$post[$postfield] = curl_file_create($file_path);
|
||||
}
|
||||
else {
|
||||
// @todo: Drop support for this when PHP 5.5 is required.
|
||||
$post[$key] = '@' . $file;
|
||||
}
|
||||
else {
|
||||
$file = $this->container->get('file_system')->realpath($file);
|
||||
if ($file && is_file($file)) {
|
||||
$post[$key] = curl_file_create($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1735,8 +1769,7 @@ abstract class WebTestBase extends TestBase {
|
|||
* and the value is the button label. i.e.) array('op' => t('Refresh')).
|
||||
* @param $ajax_path
|
||||
* (optional) Override the path set by the Ajax settings of the triggering
|
||||
* element. In the absence of both the triggering element's Ajax path and
|
||||
* $ajax_path 'system/ajax' will be used.
|
||||
* element.
|
||||
* @param $options
|
||||
* (optional) Options to be forwarded to the url generator.
|
||||
* @param $headers
|
||||
|
@ -1807,7 +1840,7 @@ abstract class WebTestBase extends TestBase {
|
|||
$extra_post = '&' . $this->serializePostValues($extra_post);
|
||||
|
||||
// Unless a particular path is specified, use the one specified by the
|
||||
// Ajax settings, or else 'system/ajax'.
|
||||
// Ajax settings.
|
||||
if (!isset($ajax_path)) {
|
||||
if (isset($ajax_settings['url'])) {
|
||||
// In order to allow to set for example the wrapper envelope query
|
||||
|
@ -1824,10 +1857,12 @@ abstract class WebTestBase extends TestBase {
|
|||
$parsed_url['path']
|
||||
);
|
||||
}
|
||||
else {
|
||||
$ajax_path = 'system/ajax';
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($ajax_path)) {
|
||||
throw new \Exception('No #ajax path specified.');
|
||||
}
|
||||
|
||||
$ajax_path = $this->container->get('unrouted_url_assembler')->assemble('base://' . $ajax_path, $options);
|
||||
|
||||
// Submit the POST request.
|
||||
|
@ -2324,7 +2359,7 @@ abstract class WebTestBase extends TestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Follows a link by name.
|
||||
* Follows a link by complete name.
|
||||
*
|
||||
* Will click the first link found with this link text by default, or a later
|
||||
* one if an index is given. Match is case sensitive with normalized space.
|
||||
|
@ -2332,17 +2367,54 @@ abstract class WebTestBase extends TestBase {
|
|||
*
|
||||
* If the link is discovered and clicked, the test passes. Fail otherwise.
|
||||
*
|
||||
* @param $label
|
||||
* @param string $label
|
||||
* Text between the anchor tags.
|
||||
* @param $index
|
||||
* @param int $index
|
||||
* Link position counting from zero.
|
||||
*
|
||||
* @return
|
||||
* @return string|bool
|
||||
* Page contents on success, or FALSE on failure.
|
||||
*/
|
||||
protected function clickLink($label, $index = 0) {
|
||||
return $this->clickLinkHelper($label, $index, '//a[normalize-space()=:label]');
|
||||
}
|
||||
|
||||
/**
|
||||
* Follows a link by partial name.
|
||||
*
|
||||
*
|
||||
* If the link is discovered and clicked, the test passes. Fail otherwise.
|
||||
*
|
||||
* @param string $label
|
||||
* Text between the anchor tags, uses starts-with().
|
||||
* @param int $index
|
||||
* Link position counting from zero.
|
||||
*
|
||||
* @return string|bool
|
||||
* Page contents on success, or FALSE on failure.
|
||||
*
|
||||
* @see ::clickLink()
|
||||
*/
|
||||
protected function clickLinkPartialName($label, $index = 0) {
|
||||
return $this->clickLinkHelper($label, $index, '//a[starts-with(normalize-space(), :label)]');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a helper for ::clickLink() and ::clickLinkPartialName().
|
||||
*
|
||||
* @param string $label
|
||||
* Text between the anchor tags, uses starts-with().
|
||||
* @param int $index
|
||||
* Link position counting from zero.
|
||||
* @param string $pattern
|
||||
* A pattern to use for the XPath.
|
||||
*
|
||||
* @return bool|string
|
||||
* Page contents on success, or FALSE on failure.
|
||||
*/
|
||||
protected function clickLinkHelper($label, $index, $pattern) {
|
||||
$url_before = $this->getUrl();
|
||||
$urls = $this->xpath('//a[normalize-space()=:label]', array(':label' => $label));
|
||||
$urls = $this->xpath($pattern, array(':label' => $label));
|
||||
if (isset($urls[$index])) {
|
||||
$url_target = $this->getAbsoluteUrl($urls[$index]['href']);
|
||||
$this->pass(SafeMarkup::format('Clicked link %label (@url_target) from @url_before', array('%label' => $label, '@url_target' => $url_target, '@url_before' => $url_before)), 'Browser');
|
||||
|
@ -2355,16 +2427,35 @@ abstract class WebTestBase extends TestBase {
|
|||
/**
|
||||
* Takes a path and returns an absolute path.
|
||||
*
|
||||
* @param $path
|
||||
* This method is implemented in the way that browsers work, see
|
||||
* https://url.spec.whatwg.org/#relative-state for more information about the
|
||||
* possible cases.
|
||||
*
|
||||
* @param string $path
|
||||
* A path from the internal browser content.
|
||||
*
|
||||
* @return
|
||||
* @return string
|
||||
* The $path with $base_url prepended, if necessary.
|
||||
*/
|
||||
protected function getAbsoluteUrl($path) {
|
||||
global $base_url, $base_path;
|
||||
|
||||
$parts = parse_url($path);
|
||||
|
||||
// In case the $path has a host, it is already an absolute URL and we are
|
||||
// done.
|
||||
if (!empty($parts['host'])) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
// In case the $path contains just a query, we turn it into an absolute URL
|
||||
// with the same scheme, host and path, see
|
||||
// https://url.spec.whatwg.org/#relative-state.
|
||||
if (array_keys($parts) === ['query']) {
|
||||
$current_uri = new Uri($this->getUrl());
|
||||
return (string) $current_uri->withQuery($parts['query']);
|
||||
}
|
||||
|
||||
if (empty($parts['host'])) {
|
||||
// Ensure that we have a string (and no xpath object).
|
||||
$path = (string) $path;
|
||||
|
@ -2822,6 +2913,17 @@ abstract class WebTestBase extends TestBase {
|
|||
$this->assertTrue(in_array($expected_cache_context, $cache_contexts), "'" . $expected_cache_context . "' is present in the X-Drupal-Cache-Contexts header.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a cache context was not present in the last response.
|
||||
*
|
||||
* @param string $not_expected_cache_context
|
||||
* The expected cache context.
|
||||
*/
|
||||
protected function assertNoCacheContext($not_expected_cache_context) {
|
||||
$cache_contexts = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Contexts'));
|
||||
$this->assertFalse(in_array($not_expected_cache_context, $cache_contexts), "'" . $not_expected_cache_context . "' is not present in the X-Drupal-Cache-Contexts header.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts whether an expected cache tag was present in the last response.
|
||||
*
|
||||
|
|
|
@ -115,10 +115,11 @@ class TestBaseTest extends UnitTestCase {
|
|||
$mock_test_base = $this->getMockForAbstractClass('Drupal\simpletest\TestBase');
|
||||
$string = $mock_test_base->randomString($length);
|
||||
$this->assertEquals($length, strlen($string));
|
||||
// randomString() should always include an ampersand ('&') if $length is
|
||||
// greater than 2.
|
||||
if ($length > 2) {
|
||||
// randomString() should always include an ampersand ('&') and a
|
||||
// greater than ('>') if $length is greater than 3.
|
||||
if ($length > 3) {
|
||||
$this->assertContains('&', $string);
|
||||
$this->assertContains('>', $string);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -198,4 +198,41 @@ class WebTestBaseTest extends UnitTestCase {
|
|||
$this->assertSame($expected, $clicklink_method->invoke($web_test, $label, $index));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerTestGetAbsoluteUrl
|
||||
*/
|
||||
public function testGetAbsoluteUrl($href, $expected_absolute_path) {
|
||||
$web_test = $this->getMockBuilder('Drupal\simpletest\WebTestBase')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['getUrl'])
|
||||
->getMock();
|
||||
|
||||
$web_test->expects($this->any())
|
||||
->method('getUrl')
|
||||
->willReturn('http://example.com/drupal/current-path?foo=baz');
|
||||
|
||||
$GLOBALS['base_url'] = 'http://example.com';
|
||||
$GLOBALS['base_path'] = 'drupal';
|
||||
|
||||
$get_absolute_url_method = new \ReflectionMethod($web_test, 'getAbsoluteUrl');
|
||||
$get_absolute_url_method->setAccessible(TRUE);
|
||||
|
||||
$this->assertSame($expected_absolute_path, $get_absolute_url_method->invoke($web_test, $href));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testGetAbsoluteUrl.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestGetAbsoluteUrl() {
|
||||
$data = [];
|
||||
$data['host'] = ['http://example.com/drupal/test-example', 'http://example.com/drupal/test-example'];
|
||||
$data['path'] = ['/drupal/test-example', 'http://example.com/drupal/test-example'];
|
||||
$data['path-with-query'] = ['/drupal/test-example?foo=bar', 'http://example.com/drupal/test-example?foo=bar'];
|
||||
$data['just-query'] = ['?foo=bar', 'http://example.com/drupal/current-path?foo=bar'];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Reference in a new issue