Update to Drupal 8.0.6. For more information, see https://www.drupal.org/drupal-8.0.6-release-notes

This commit is contained in:
Pantheon Automation 2016-04-07 11:19:57 -07:00 committed by Greg Anderson
parent 4297c64508
commit b11a755ba8
159 changed files with 2340 additions and 543 deletions

View file

@ -489,9 +489,10 @@ function simpletest_log_read($test_id, $database_prefix, $test_class) {
* each module for files matching the PSR-0 standard. Once loaded the test list
* is cached and stored in a static variable.
*
* @param string $module
* Name of a module. If set then only tests belonging to this module are
* returned.
* @param string $extension
* (optional) The name of an extension to limit discovery to; e.g., 'node'.
* @param string[] $types
* An array of included test types.
*
* @return array[]
* An array of tests keyed with the groups, and then keyed by test classes.
@ -506,8 +507,8 @@ function simpletest_log_read($test_id, $database_prefix, $test_class) {
* );
* @endcode
*/
function simpletest_test_get_all($module = NULL) {
return \Drupal::service('test_discovery')->getTestClasses($module);
function simpletest_test_get_all($extension = NULL, array $types = []) {
return \Drupal::service('test_discovery')->getTestClasses($extension, $types);
}
/**

View file

@ -1,4 +1,4 @@
services:
test_discovery:
class: Drupal\simpletest\TestDiscovery
arguments: ['@class_loader', '@?cache.discovery']
arguments: ['@app.root', '@class_loader', '@module_handler', '@?cache.discovery']

View file

@ -23,7 +23,7 @@ trait AssertHelperTrait {
* @return mixed
* The input value, with MarkupInterface objects casted to string.
*/
protected function castSafeStrings($value) {
protected static function castSafeStrings($value) {
if ($value instanceof MarkupInterface) {
$value = (string) $value;
}

View file

@ -229,11 +229,17 @@ abstract class BrowserTestBase extends \PHPUnit_Framework_TestCase {
*/
protected function initMink() {
$driver = $this->getDefaultDriverInstance();
if ($driver instanceof GoutteDriver) {
$driver->getClient()->setClient(\Drupal::httpClient());
}
$session = new Session($driver);
$this->mink = new Mink();
$this->mink->registerSession('default', $session);
$this->mink->setDefaultSessionName('default');
$this->registerSessions();
return $session;
}

View file

@ -271,6 +271,12 @@ EOD;
// The temporary stream wrapper is able to operate both with and without
// configuration.
$this->registerStreamWrapper('temporary', 'Drupal\Core\StreamWrapper\TemporaryStream');
// Manually configure the test mail collector implementation to prevent
// tests from sending out emails and collect them in state instead.
// While this should be enforced via settings.php prior to installation,
// some tests expect to be able to test mail system implementations.
$GLOBALS['config']['system.mail']['interface']['default'] = 'test_mail_collector';
}
/**

View file

@ -10,9 +10,11 @@ namespace Drupal\simpletest;
use Doctrine\Common\Annotations\SimpleAnnotationReader;
use Doctrine\Common\Reflection\StaticReflectionParser;
use Drupal\Component\Annotation\Reflection\MockFileFinder;
use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ExtensionDiscovery;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\simpletest\Exception\MissingGroupException;
use PHPUnit_Util_Test;
@ -49,18 +51,38 @@ class TestDiscovery {
*/
protected $availableExtensions;
/**
* The app root.
*
* @var string
*/
protected $root;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Constructs a new test discovery.
*
* @param string $root
* The app root.
* @param $class_loader
* The class loader. Normally Composer's ClassLoader, as included by the
* front controller, but may also be decorated; e.g.,
* \Symfony\Component\ClassLoader\ApcClassLoader.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* (optional) Backend for caching discovery results.
*/
public function __construct($class_loader, CacheBackendInterface $cache_backend = NULL) {
public function __construct($root, $class_loader, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend = NULL) {
$this->root = $root;
$this->classLoader = $class_loader;
$this->moduleHandler = $module_handler;
$this->cacheBackend = $cache_backend;
}
@ -80,15 +102,16 @@ class TestDiscovery {
$existing = $this->classLoader->getPrefixesPsr4();
// Add PHPUnit test namespaces of Drupal core.
$this->testNamespaces['Drupal\\Tests\\'] = [DRUPAL_ROOT . '/core/tests/Drupal/Tests'];
$this->testNamespaces['Drupal\\KernelTests\\'] = [DRUPAL_ROOT . '/core/tests/Drupal/KernelTests'];
$this->testNamespaces['Drupal\\FunctionalTests\\'] = [DRUPAL_ROOT . '/core/tests/Drupal/FunctionalTests'];
$this->testNamespaces['Drupal\\Tests\\'] = [$this->root . '/core/tests/Drupal/Tests'];
$this->testNamespaces['Drupal\\KernelTests\\'] = [$this->root . '/core/tests/Drupal/KernelTests'];
$this->testNamespaces['Drupal\\FunctionalTests\\'] = [$this->root . '/core/tests/Drupal/FunctionalTests'];
$this->testNamespaces['Drupal\\FunctionalJavascriptTests\\'] = [$this->root . '/core/tests/Drupal/FunctionalJavascriptTests'];
$this->availableExtensions = array();
foreach ($this->getExtensions() as $name => $extension) {
$this->availableExtensions[$extension->getType()][$name] = $name;
$base_path = DRUPAL_ROOT . '/' . $extension->getPath();
$base_path = $this->root . '/' . $extension->getPath();
// Add namespace of disabled/uninstalled extensions.
if (!isset($existing["Drupal\\$name\\"])) {
@ -115,11 +138,12 @@ class TestDiscovery {
*
* @param string $extension
* (optional) The name of an extension to limit discovery to; e.g., 'node'.
* @param string[] $types
* An array of included test types.
*
* @return array
* An array of tests keyed by the first @group specified in each test's
* PHPDoc comment block, and then keyed by class names. For example:
* @code
* An array of tests keyed by the the group name.
* @code
* $groups['block'] => array(
* 'Drupal\block\Tests\BlockTest' => array(
* 'name' => 'Drupal\block\Tests\BlockTest',
@ -127,15 +151,12 @@ class TestDiscovery {
* 'group' => 'block',
* ),
* );
* @endcode
*
* @throws \ReflectionException
* If a discovered test class does not match the expected class name.
* @endcode
*
* @todo Remove singular grouping; retain list of groups in 'group' key.
* @see https://www.drupal.org/node/2296615
*/
public function getTestClasses($extension = NULL) {
public function getTestClasses($extension = NULL, array $types = []) {
$reader = new SimpleAnnotationReader();
$reader->addNamespace('Drupal\\simpletest\\Annotation');
@ -190,13 +211,20 @@ class TestDiscovery {
}
// Allow modules extending core tests to disable originals.
\Drupal::moduleHandler()->alter('simpletest', $list);
$this->moduleHandler->alter('simpletest', $list);
if (!isset($extension)) {
if ($this->cacheBackend) {
$this->cacheBackend->set('simpletest:discovery:classes', $list);
}
}
if ($types) {
$list = NestedArray::filter($list, function ($element) use ($types) {
return !(is_array($element) && isset($element['type']) && !in_array($element['type'], $types));
});
}
return $list;
}
@ -450,7 +478,7 @@ class TestDiscovery {
* An array of Extension objects, keyed by extension name.
*/
protected function getExtensions() {
$listing = new ExtensionDiscovery(DRUPAL_ROOT);
$listing = new ExtensionDiscovery($this->root);
// Ensure that tests in all profiles are discovered.
$listing->setProfileDirectories(array());
$extensions = $listing->scan('module', TRUE);

View file

@ -28,6 +28,7 @@ use Drupal\Core\Session\AnonymousUserSession;
use Drupal\Core\Session\UserSession;
use Drupal\Core\Site\Settings;
use Drupal\Core\StreamWrapper\PublicStream;
use Drupal\Core\Test\AssertMailTrait;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
@ -47,6 +48,9 @@ abstract class WebTestBase extends TestBase {
use ContentTypeCreationTrait {
createContentType as drupalCreateContentType;
}
use AssertMailTrait {
getMails as drupalGetMails;
}
use NodeCreationTrait {
getNodeByTitle as drupalGetNodeByTitle;
createNode as drupalCreateNode;
@ -2518,32 +2522,6 @@ abstract class WebTestBase extends TestBase {
return $this->assertTrue($header_value == $value, $message ? $message : 'HTTP response header ' . $header . ' with value ' . $value . ' found, actual value: ' . $header_value, $group);
}
/**
* Gets an array containing all emails sent during this test case.
*
* @param $filter
* An array containing key/value pairs used to filter the emails that are
* returned.
*
* @return
* An array containing email messages captured during the current test.
*/
protected function drupalGetMails($filter = array()) {
$captured_emails = \Drupal::state()->get('system.test_mail_collector') ?: array();
$filtered_emails = array();
foreach ($captured_emails as $message) {
foreach ($filter as $key => $value) {
if (!isset($message[$key]) || $message[$key] != $value) {
continue 2;
}
}
$filtered_emails[] = $message;
}
return $filtered_emails;
}
/**
* Passes if the internal browser's URL matches the given path.
*
@ -2644,126 +2622,6 @@ abstract class WebTestBase extends TestBase {
return $this->assertFalse($match, $message ? $message : SafeMarkup::format('HTTP response not expected @code, actual @curl_code', array('@code' => $code, '@curl_code' => $curl_code)), $group);
}
/**
* Asserts that the most recently sent email message has the given value.
*
* The field in $name must have the content described in $value.
*
* @param $name
* Name of field or message property to assert. Examples: subject, body,
* id, ...
* @param $value
* Value of the field to assert.
* @param $message
* (optional) A message to display with the assertion. Do not translate
* messages: use \Drupal\Component\Utility\SafeMarkup::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
* @param $group
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Email'; most tests do not override
* this default.
*
* @return
* TRUE on pass, FALSE on fail.
*/
protected function assertMail($name, $value = '', $message = '', $group = 'Email') {
$captured_emails = \Drupal::state()->get('system.test_mail_collector') ?: array();
$email = end($captured_emails);
return $this->assertTrue($email && isset($email[$name]) && $email[$name] == $value, $message, $group);
}
/**
* Asserts that the most recently sent email message has the string in it.
*
* @param $field_name
* Name of field or message property to assert: subject, body, id, ...
* @param $string
* String to search for.
* @param $email_depth
* Number of emails to search for string, starting with most recent.
* @param $message
* (optional) A message to display with the assertion. Do not translate
* messages: use \Drupal\Component\Utility\SafeMarkup::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
* @param $group
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
* @return
* TRUE on pass, FALSE on fail.
*/
protected function assertMailString($field_name, $string, $email_depth, $message = '', $group = 'Other') {
$mails = $this->drupalGetMails();
$string_found = FALSE;
// Cast MarkupInterface objects to string.
$string = (string) $string;
for ($i = count($mails) -1; $i >= count($mails) - $email_depth && $i >= 0; $i--) {
$mail = $mails[$i];
// Normalize whitespace, as we don't know what the mail system might have
// done. Any run of whitespace becomes a single space.
$normalized_mail = preg_replace('/\s+/', ' ', $mail[$field_name]);
$normalized_string = preg_replace('/\s+/', ' ', $string);
$string_found = (FALSE !== strpos($normalized_mail, $normalized_string));
if ($string_found) {
break;
}
}
if (!$message) {
$message = format_string('Expected text found in @field of email message: "@expected".', array('@field' => $field_name, '@expected' => $string));
}
return $this->assertTrue($string_found, $message, $group);
}
/**
* Asserts that the most recently sent email message has the pattern in it.
*
* @param $field_name
* Name of field or message property to assert: subject, body, id, ...
* @param $regex
* Pattern to search for.
* @param $message
* (optional) A message to display with the assertion. Do not translate
* messages: use \Drupal\Component\Utility\SafeMarkup::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
* @param $group
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
* @return
* TRUE on pass, FALSE on fail.
*/
protected function assertMailPattern($field_name, $regex, $message = '', $group = 'Other') {
$mails = $this->drupalGetMails();
$mail = end($mails);
$regex_found = preg_match("/$regex/", $mail[$field_name]);
if (!$message) {
$message = format_string('Expected text found in @field of email message: "@expected".', array('@field' => $field_name, '@expected' => $regex));
}
return $this->assertTrue($regex_found, $message, $group);
}
/**
* Outputs to verbose the most recent $count emails sent.
*
* @param $count
* Optional number of emails to output.
*/
protected function verboseEmail($count = 1) {
$mails = $this->drupalGetMails();
for ($i = count($mails) -1; $i >= count($mails) - $count && $i >= 0; $i--) {
$mail = $mails[$i];
$this->verbose('Email:<pre>' . print_r($mail, TRUE) . '</pre>');
}
}
/**
* Creates a mock request and sets it on the generator.
*

View file

@ -58,4 +58,9 @@ class BrowserTestBaseTest extends BrowserTestBase {
$this->assertSame('green', $value);
}
public function testError() {
$this->setExpectedException('\Exception', 'User notice: foo');
$this->drupalGet('test-error');
}
}

View file

@ -7,8 +7,12 @@
namespace Drupal\Tests\simpletest\Unit;
use Composer\Autoload\ClassLoader;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\simpletest\TestDiscovery;
use Drupal\Tests\UnitTestCase;
use org\bovigo\vfs\vfsStream;
/**
* @coversDefaultClass \Drupal\simpletest\TestDiscovery
@ -256,6 +260,130 @@ EOT;
$this->assertEmpty($info['description']);
}
protected function setupVfsWithTestClasses() {
vfsStream::setup('drupal');
$test_file = <<<EOF
<?php
/**
* Test description
* @group example
*/
class FunctionalExampleTest {}
EOF;
vfsStream::create([
'modules' => [
'test_module' => [
'tests' => [
'src' => [
'Functional' => [
'FunctionalExampleTest.php' => $test_file,
'FunctionalExampleTest2.php' => str_replace(['FunctionalExampleTest', '@group example'], ['FunctionalExampleTest2', '@group example2'], $test_file),
],
'Kernel' => [
'KernelExampleTest3.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleTest3', '@group example2'], $test_file),
],
],
],
],
],
]);
}
/**
* @covers ::getTestClasses
*/
public function testGetTestClasses() {
$this->setupVfsWithTestClasses();
$class_loader = $this->prophesize(ClassLoader::class);
$module_handler = $this->prophesize(ModuleHandlerInterface::class);
$test_discovery = new TestTestDiscovery('vfs://drupal', $class_loader->reveal(), $module_handler->reveal());
$extensions = [
'test_module' => new Extension('vfs://drupal', 'module', 'modules/test_module/test_module.info.yml'),
];
$test_discovery->setExtensions($extensions);
$result = $test_discovery->getTestClasses();
$this->assertCount(2, $result);
$this->assertEquals([
'example' => [
'Drupal\Tests\test_module\Functional\FunctionalExampleTest' => [
'name' => 'Drupal\Tests\test_module\Functional\FunctionalExampleTest',
'description' => 'Test description',
'group' => 'example',
'type' => 'PHPUnit-Functional',
],
],
'example2' => [
'Drupal\Tests\test_module\Functional\FunctionalExampleTest2' => [
'name' => 'Drupal\Tests\test_module\Functional\FunctionalExampleTest2',
'description' => 'Test description',
'group' => 'example2',
'type' => 'PHPUnit-Functional',
],
'Drupal\Tests\test_module\Kernel\KernelExampleTest3' => [
'name' => 'Drupal\Tests\test_module\Kernel\KernelExampleTest3',
'description' => 'Test description',
'group' => 'example2',
'type' => 'PHPUnit-Kernel',
],
],
], $result);
}
/**
* @covers ::getTestClasses
*/
public function testGetTestClassesWithSelectedTypes() {
$this->setupVfsWithTestClasses();
$class_loader = $this->prophesize(ClassLoader::class);
$module_handler = $this->prophesize(ModuleHandlerInterface::class);
$test_discovery = new TestTestDiscovery('vfs://drupal', $class_loader->reveal(), $module_handler->reveal());
$extensions = [
'test_module' => new Extension('vfs://drupal', 'module', 'modules/test_module/test_module.info.yml'),
];
$test_discovery->setExtensions($extensions);
$result = $test_discovery->getTestClasses(NULL, ['PHPUnit-Kernel']);
$this->assertCount(2, $result);
$this->assertEquals([
'example' => [
],
'example2' => [
'Drupal\Tests\test_module\Kernel\KernelExampleTest3' => [
'name' => 'Drupal\Tests\test_module\Kernel\KernelExampleTest3',
'description' => 'Test description',
'group' => 'example2',
'type' => 'PHPUnit-Kernel',
],
],
], $result);
}
}
class TestTestDiscovery extends TestDiscovery {
/**
* @var \Drupal\Core\Extension\Extension[]
*/
protected $extensions = [];
public function setExtensions(array $extensions) {
$this->extensions = $extensions;
}
/**
* {@inheritdoc}
*/
protected function getExtensions() {
return $this->extensions;
}
/**
* @covers ::getPhpunitTestSuite
* @dataProvider providerTestGetPhpunitTestSuite