updated core

This commit is contained in:
Bachir Soussi Chiadmi
2018-01-24 13:36:32 +01:00
parent cd7dea45a9
commit f9374cf96d
1997 changed files with 5175 additions and 127715 deletions
+30 -11
View File
@@ -35,6 +35,10 @@ use Symfony\Component\CssSelector\CssSelectorConverter;
* Drupal\Tests\yourmodule\Functional namespace and live in the
* modules/yourmodule/tests/src/Functional directory.
*
* Tests extending this base class should only translate text when testing
* translation functionality. For example, avoid wrapping test text with t()
* or TranslatableMarkup().
*
* @ingroup testing
*/
abstract class BrowserTestBase extends TestCase {
@@ -62,6 +66,7 @@ abstract class BrowserTestBase extends TestCase {
createUser as drupalCreateUser;
}
use XdebugRequestTrait;
use PhpunitCompatibilityTrait;
/**
* The database prefix of this test run.
@@ -342,7 +347,7 @@ abstract class BrowserTestBase extends TestCase {
protected function getDefaultDriverInstance() {
// Get default driver params from environment if availables.
if ($arg_json = getenv('MINK_DRIVER_ARGS')) {
$this->minkDefaultDriverArgs = json_decode($arg_json);
$this->minkDefaultDriverArgs = json_decode($arg_json, TRUE);
}
// Get and check default driver class from environment if availables.
@@ -446,6 +451,15 @@ abstract class BrowserTestBase extends TestCase {
* {@inheritdoc}
*/
protected function setUp() {
// Installing Drupal creates 1000s of objects. Garbage collection of these
// objects is expensive. This appears to be causing random segmentation
// faults in PHP 5.x due to https://bugs.php.net/bug.php?id=72286. Once
// Drupal is installed is rebuilt, garbage collection is re-enabled.
$disable_gc = version_compare(PHP_VERSION, '7', '<') && gc_enabled();
if ($disable_gc) {
gc_collect_cycles();
gc_disable();
}
parent::setUp();
$this->setupBaseUrl();
@@ -466,6 +480,11 @@ abstract class BrowserTestBase extends TestCase {
// Set up the browser test output file.
$this->initBrowserOutputFile();
// If garbage collection was disabled prior to rebuilding container,
// re-enable it.
if ($disable_gc) {
gc_enable();
}
}
/**
@@ -777,10 +796,10 @@ abstract class BrowserTestBase extends TestCase {
* be unchecked.
* @param string $submit
* Value of the submit button whose click is to be emulated. For example,
* t('Save'). The processing of the request depends on this value. For
* example, a form may have one button with the value t('Save') and another
* button with the value t('Delete'), and execute different code depending
* on which one is clicked.
* 'Save'. The processing of the request depends on this value. For example,
* a form may have one button with the value 'Save' and another button with
* the value 'Delete', and execute different code depending on which one is
* clicked.
* @param string $form_html_id
* (optional) HTML ID of the form to be submitted. On some pages
* there are many identical forms, so just using the value of the submit
@@ -859,11 +878,11 @@ abstract class BrowserTestBase extends TestCase {
* @code
* // First step in form.
* $edit = array(...);
* $this->drupalPostForm('some_url', $edit, t('Save'));
* $this->drupalPostForm('some_url', $edit, 'Save');
*
* // Second step in form.
* $edit = array(...);
* $this->drupalPostForm(NULL, $edit, t('Save'));
* $this->drupalPostForm(NULL, $edit, 'Save');
* @endcode
* @param array $edit
* Field data in an associative array. Changes the current input fields
@@ -893,10 +912,10 @@ abstract class BrowserTestBase extends TestCase {
* https://www.drupal.org/node/2802401
* @param string $submit
* Value of the submit button whose click is to be emulated. For example,
* t('Save'). The processing of the request depends on this value. For
* example, a form may have one button with the value t('Save') and another
* button with the value t('Delete'), and execute different code depending
* on which one is clicked.
* 'Save'. The processing of the request depends on this value. For example,
* a form may have one button with the value 'Save' and another button with
* the value 'Delete', and execute different code depending on which one is
* clicked.
*
* 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:
@@ -167,7 +167,7 @@ class DateTimePlusTest extends TestCase {
* Assertion helper for testTimestamp and testDateTimestamp since they need
* different dataProviders.
*
* @param DateTimePlus $date
* @param \Drupal\Component\Datetime\DateTimePlus $date
* DateTimePlus to test.
* @input mixed $input
* The original input passed to the test method.
@@ -1043,7 +1043,7 @@ class MockInstantiationService {
class MockService {
/**
* @var ContainerInterface
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
protected $container;
@@ -1081,7 +1081,7 @@ class MockService {
/**
* Sets the container object.
*
* @param ContainerInterface $container
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* The container to inject via setter injection.
*/
public function setContainer(ContainerInterface $container) {
@@ -1091,7 +1091,7 @@ class MockService {
/**
* Gets the container object.
*
* @return ContainerInterface
* @return \Symfony\Component\DependencyInjection\ContainerInterface
* The internally set container.
*/
public function getContainer() {
@@ -125,7 +125,6 @@ class FileCacheFactoryTest extends TestCase {
$class,
];
// Test default configuration plus specific per collection setting.
$data['default-plus-collection-setting'] = [
[
@@ -4,6 +4,8 @@ namespace Drupal\Tests\Component\PhpStorage;
use Drupal\Component\PhpStorage\FileStorage;
use Drupal\Component\Utility\Random;
use org\bovigo\vfs\vfsStreamDirectory;
use PHPUnit_Framework_Error_Warning;
/**
* @coversDefaultClass \Drupal\Component\PhpStorage\FileStorage
@@ -87,4 +89,18 @@ class FileStorageTest extends PhpStorageTestBase {
unset($GLOBALS[$random]);
}
/**
* @covers ::createDirectory
*/
public function testCreateDirectoryFailWarning() {
$directory = new vfsStreamDirectory('permissionDenied', 0200);
$storage = new FileStorage([
'directory' => $directory->url(),
'bin' => 'test',
]);
$code = "<?php\n echo 'here';";
$this->setExpectedException(PHPUnit_Framework_Error_Warning::class, 'mkdir(): Permission Denied');
$storage->save('subdirectory/foo.php', $code);
}
}
@@ -67,9 +67,10 @@ class HtmlTest extends TestCase {
[$id1, $id1, []],
// Verify that valid UTF-8 characters are not stripped from the identifier.
[$id2, $id2, []],
// Verify that invalid characters (including non-breaking space) are stripped from the identifier.
[$id3, $id3],
// Verify that double underscores are not stripped from the identifier.
[$id3, $id3],
// Verify that invalid characters (including non-breaking space) are
// stripped from the identifier.
['invalididentifier', 'invalid !"#$%&\'()*+,./:;<=>?@[\\]^`{|}~ identifier', []],
// Verify that an identifier starting with a digit is replaced.
['_cssidentifier', '1cssidentifier', []],
@@ -617,7 +617,6 @@ class AccessResultTest extends UnitTestCase {
[$allowed_un, 'OR', $neutral_cf, FALSE, NULL],
[$allowed_un, 'OR', $neutral_un, FALSE, NULL],
// Forbidden (ct) OR allowed (ct,cf,un).
[$forbidden_ct, 'OR', $allowed_ct, TRUE, TRUE],
[$forbidden_ct, 'OR', $allowed_cf, TRUE, TRUE],
@@ -657,7 +656,6 @@ class AccessResultTest extends UnitTestCase {
[$forbidden_un, 'OR', $forbidden_cf, FALSE, NULL],
[$forbidden_un, 'OR', $forbidden_un, FALSE, NULL],
// Neutral (ct) OR allowed (ct,cf,un).
[$neutral_ct, 'OR', $allowed_ct, TRUE, TRUE],
[$neutral_ct, 'OR', $allowed_cf, TRUE, FALSE],
@@ -697,7 +695,6 @@ class AccessResultTest extends UnitTestCase {
[$neutral_un, 'OR', $forbidden_cf, FALSE, NULL],
[$neutral_un, 'OR', $forbidden_un, FALSE, NULL],
// Allowed (ct) AND allowed (ct,cf,un).
[$allowed_ct, 'AND', $allowed_ct, TRUE, TRUE],
[$allowed_ct, 'AND', $allowed_cf, TRUE, FALSE],
@@ -737,7 +734,6 @@ class AccessResultTest extends UnitTestCase {
[$allowed_un, 'AND', $neutral_cf, FALSE, NULL],
[$allowed_un, 'AND', $neutral_un, FALSE, NULL],
// Forbidden (ct) AND allowed (ct,cf,un).
[$forbidden_ct, 'AND', $allowed_ct, TRUE, TRUE],
[$forbidden_ct, 'AND', $allowed_cf, TRUE, TRUE],
@@ -777,7 +773,6 @@ class AccessResultTest extends UnitTestCase {
[$forbidden_un, 'AND', $forbidden_cf, FALSE, NULL],
[$forbidden_un, 'AND', $forbidden_un, FALSE, NULL],
// Neutral (ct) AND allowed (ct,cf,un).
[$neutral_ct, 'AND', $allowed_ct, TRUE, TRUE],
[$neutral_ct, 'AND', $allowed_cf, TRUE, TRUE],
@@ -25,6 +25,7 @@ use Drupal\Core\Ajax\SetDialogOptionCommand;
use Drupal\Core\Ajax\SetDialogTitleCommand;
use Drupal\Core\Ajax\RedirectCommand;
use Drupal\Core\Ajax\UpdateBuildIdCommand;
use Drupal\Core\Ajax\OpenDialogCommand;
/**
* Test coverage for various classes in the \Drupal\Core\Ajax namespace.
@@ -293,27 +294,16 @@ class AjaxCommandsTest extends UnitTestCase {
* @covers \Drupal\Core\Ajax\OpenDialogCommand
*/
public function testOpenDialogCommand() {
$command = $this->getMockBuilder('Drupal\Core\Ajax\OpenDialogCommand')
->setConstructorArgs([
'#some-dialog', 'Title', '<p>Text!</p>', [
'url' => FALSE,
'width' => 500,
],
])
->setMethods(['getRenderedContent'])
->getMock();
// This method calls the render service, which isn't available. We want it
// to do nothing so we mock it to return a known value.
$command->expects($this->once())
->method('getRenderedContent')
->willReturn('rendered content');
$command = new OpenDialogCommand('#some-dialog', 'Title', '<p>Text!</p>', [
'url' => FALSE,
'width' => 500,
]);
$expected = [
'command' => 'openDialog',
'selector' => '#some-dialog',
'settings' => NULL,
'data' => 'rendered content',
'data' => '<p>Text!</p>',
'dialogOptions' => [
'url' => FALSE,
'width' => 500,
@@ -322,6 +312,10 @@ class AjaxCommandsTest extends UnitTestCase {
],
];
$this->assertEquals($expected, $command->render());
$command->setDialogTitle('New title');
$expected['dialogOptions']['title'] = 'New title';
$this->assertEquals($expected, $command->render());
}
/**
@@ -97,7 +97,7 @@ class BackendCompilerPassTest extends UnitTestCase {
* bag so the setParameter() call effects the parent container as well.
*
* @param $service
* @return ContainerBuilder
* @return \Symfony\Component\DependencyInjection\ContainerBuilder
*/
protected function getSqliteContainer($service) {
$container = new ContainerBuilder();
@@ -115,7 +115,7 @@ class BackendCompilerPassTest extends UnitTestCase {
* bag so the setParameter() call effects the parent container as well.
*
* @param $service
* @return ContainerBuilder
* @return \Symfony\Component\DependencyInjection\ContainerBuilder
*/
protected function getMysqlContainer($service) {
$container = new ContainerBuilder();
@@ -112,7 +112,7 @@ class EntityAccessCheckTest extends UnitTestCase {
*
* @param \stdClass $object
* Any object, including prophesized mocks based on interfaces.
* @return RouteMatchInterface
* @return \Drupal\Core\Routing\RouteMatchInterface
* A prophesized RouteMatchInterface.
*/
private function createRouteMatchForObject(\stdClass $object) {
@@ -439,7 +439,6 @@ class EntityFieldManagerTest extends UnitTestCase {
})
->shouldBeCalled();
$this->assertSame($expected, $this->entityFieldManager->getFieldStorageDefinitions('test_entity_type'));
$this->entityFieldManager->testClearEntityFieldInfo();
$this->assertSame($expected, $this->entityFieldManager->getFieldStorageDefinitions('test_entity_type'));
@@ -1,42 +0,0 @@
<?php
namespace Drupal\Tests\Core\EventSubscriber;
use Drupal\Core\EventSubscriber\DefaultExceptionSubscriber;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* @coversDefaultClass \Drupal\Core\EventSubscriber\DefaultExceptionSubscriber
* @group EventSubscriber
*/
class DefaultExceptionSubscriberTest extends UnitTestCase {
/**
* @covers ::onException
* @covers ::onFormatUnknown
*/
public function testOnExceptionWithUnknownFormat() {
$config_factory = $this->getConfigFactoryStub();
$kernel = $this->prophesize(HttpKernelInterface::class);
$request = Request::create('/test?_format=bananas');
$e = new MethodNotAllowedHttpException(['POST', 'PUT'], 'test message');
$event = new GetResponseForExceptionEvent($kernel->reveal(), $request, 'GET', $e);
$subscriber = new DefaultExceptionSubscriber($config_factory);
$subscriber->onException($event);
$response = $event->getResponse();
$this->assertInstanceOf(Response::class, $response);
$this->assertEquals('test message', $response->getContent());
$this->assertEquals(405, $response->getStatusCode());
$this->assertEquals('POST, PUT', $response->headers->get('Allow'));
// Also check that that text/plain content type was added.
$this->assertEquals('text/plain', $response->headers->get('Content-Type'));
}
}
@@ -67,7 +67,7 @@ class RedirectResponseSubscriberTest extends UnitTestCase {
/**
* Test destination detection and redirection.
*
* @param Request $request
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object with destination query set.
* @param string|bool $expected
* The expected target URL or FALSE.
@@ -100,7 +100,6 @@ D rupal is an open source content management platform powering millions of websi
</rss>
RSS;
$data['invalid-feed'] = [$invalid_feed, $invalid_feed];
return $data;
}
@@ -8,4 +8,5 @@
/**
* Test hook.
*/
function module_handler_test_hook_include() {}
function module_handler_test_hook_include() {
}
@@ -5,8 +5,8 @@ package: Testing
# version: VERSION
# core: 8.x
# Information added by Drupal.org packaging script on 2017-11-03
version: '8.4.2'
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
core: '8.x'
project: 'drupal'
datestamp: 1509719929
datestamp: 1515021228
@@ -6,8 +6,8 @@ package: Testing
# core: 8.x
hidden: true
# Information added by Drupal.org packaging script on 2017-11-03
version: '8.4.2'
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
core: '8.x'
project: 'drupal'
datestamp: 1509719929
datestamp: 1515021228
@@ -6,8 +6,8 @@ package: Testing
# core: 8.x
hidden: true
# Information added by Drupal.org packaging script on 2017-11-03
version: '8.4.2'
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
core: '8.x'
project: 'drupal'
datestamp: 1509719929
datestamp: 1515021228
@@ -6,8 +6,8 @@ package: Testing
# core: 8.x
hidden: true
# Information added by Drupal.org packaging script on 2017-11-03
version: '8.4.2'
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
core: '8.x'
project: 'drupal'
datestamp: 1509719929
datestamp: 1515021228
@@ -5,8 +5,8 @@ package: Testing
# version: VERSION
# core: 8.x
# Information added by Drupal.org packaging script on 2017-11-03
version: '8.4.2'
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
core: '8.x'
project: 'drupal'
datestamp: 1509719929
datestamp: 1515021228
@@ -28,10 +28,24 @@ class FieldItemListTest extends UnitTestCase {
$container->set('plugin.manager.field.field_type', $field_type_manager);
\Drupal::setContainer($container);
// Set up three properties, one of them being computed.
$property_definitions['0'] = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$property_definitions['0']->expects($this->any())
->method('isComputed')
->willReturn(FALSE);
$property_definitions['1'] = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$property_definitions['1']->expects($this->any())
->method('isComputed')
->willReturn(FALSE);
$property_definitions['2'] = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$property_definitions['2']->expects($this->any())
->method('isComputed')
->willReturn(TRUE);
$field_storage_definition = $this->getMock('Drupal\Core\Field\FieldStorageDefinitionInterface');
$field_storage_definition->expects($this->any())
->method('getColumns')
->willReturn([0 => '0', 1 => '1']);
->method('getPropertyDefinitions')
->will($this->returnValue($property_definitions));
$field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
$field_definition->expects($this->any())
->method('getFieldStorageDefinition')
@@ -95,6 +109,30 @@ class FieldItemListTest extends UnitTestCase {
// types.
$datasets[] = [TRUE, $field_item_b, $field_item_e];
/** @var \Drupal\Core\Field\FieldItemBase $field_item_f */
$field_item_f = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE);
$field_item_f->setValue(['0' => 1, '1' => 2, '2' => 3]);
/** @var \Drupal\Core\Field\FieldItemBase $field_item_g */
$field_item_g = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE);
$field_item_g->setValue(['0' => 1, '1' => 2, '2' => 4]);
// Tests field item lists where both have same values for the non-computed
// properties ('0' and '1') and a different value for the computed one
// ('2').
$datasets[] = [TRUE, $field_item_f, $field_item_g];
/** @var \Drupal\Core\Field\FieldItemBase $field_item_h */
$field_item_h = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE);
$field_item_h->setValue(['0' => 1, '1' => 2, '3' => 3]);
/** @var \Drupal\Core\Field\FieldItemBase $field_item_i */
$field_item_i = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE);
$field_item_i->setValue(['0' => 1, '1' => 2, '3' => 4]);
// Tests field item lists where both have same values for the non-computed
// properties ('0' and '1') and a different value for a property that does
// not exist ('3').
$datasets[] = [TRUE, $field_item_h, $field_item_i];
return $datasets;
}
@@ -114,10 +152,20 @@ class FieldItemListTest extends UnitTestCase {
$container->set('plugin.manager.field.field_type', $field_type_manager);
\Drupal::setContainer($container);
// Set up the properties of the field item.
$property_definitions['0'] = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$property_definitions['0']->expects($this->any())
->method('isComputed')
->willReturn(FALSE);
$property_definitions['1'] = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$property_definitions['1']->expects($this->any())
->method('isComputed')
->willReturn(FALSE);
$field_storage_definition = $this->getMock('Drupal\Core\Field\FieldStorageDefinitionInterface');
$field_storage_definition->expects($this->any())
->method('getColumns')
->willReturn([0 => '0', 1 => '1']);
->method('getPropertyDefinitions')
->will($this->returnValue($property_definitions));
$field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
$field_definition->expects($this->any())
->method('getFieldStorageDefinition')
@@ -181,7 +181,7 @@ class FormAjaxSubscriberTest extends UnitTestCase {
$this->assertSame(200, $actual_response->headers->get('X-Status-Code'));
$expected_commands[] = [
'command' => 'insert',
'method' => 'replaceWith',
'method' => 'prepend',
'selector' => NULL,
'data' => $rendered_output,
'settings' => NULL,
@@ -72,7 +72,7 @@ class ImageTest extends UnitTestCase {
*
* @param string $class_name
* The name of the GD toolkit operation class to be mocked.
* @param ImageToolkitInterface $toolkit
* @param \Drupal\Core\Image\ImageToolkitInterface $toolkit
* The image toolkit object.
*
* @return \PHPUnit_Framework_MockObject_MockObject
@@ -462,7 +462,6 @@ class LocalTaskManagerTest extends UnitTestCase {
$mock->getCacheTags()->willReturn(isset($info['cache_tags']) ? $info['cache_tags'] : []);
$mock->getCacheMaxAge()->willReturn(isset($info['cache_max_age']) ? $info['cache_max_age'] : Cache::PERMANENT);
$access_manager_map[] = [$info['route_name'], [], $this->account, TRUE, $info['access']];
$map[] = [$info['id'], [], $mock->reveal()];
@@ -133,7 +133,6 @@ class PathValidatorTest extends UnitTestCase {
->method('processInbound')
->willReturnArgument(0);
$this->assertTrue($this->pathValidator->isValid('test-path'));
}
@@ -163,7 +163,6 @@ class BubbleableMetadataTest extends UnitTestCase {
],
];
$expected_when_empty_metadata = [
'#cache' => [
'contexts' => [],
@@ -228,7 +227,6 @@ class BubbleableMetadataTest extends UnitTestCase {
],
];
$data[] = [$empty_render_array, $empty_metadata];
$data[] = [$nonempty_render_array, $nonempty_metadata];
@@ -202,6 +202,22 @@ class HtmlTagTest extends RendererTestBase {
];
$tags['linearGradient'] = [$element, '<linearGradient><stop offset="5%" stop-color="#F60" />' . "\n" . '<stop offset="95%" stop-color="#FF6" />' . "\n" . '</linearGradient>' . "\n"];
// Simple link.
$element = [
'#tag' => 'link',
];
$tags['link'] = [HtmlTag::preRenderConditionalComments($element), '<link />' . "\n"];
// Conditional link.
$element = [
'#tag' => 'link',
'#browsers' => [
'IE' => TRUE,
'!IE' => FALSE,
],
];
$tags['conditional-link'] = [HtmlTag::preRenderConditionalComments($element), "\n" . '<!--[if IE]>' . "\n" . '<link />' . "\n" . '<![endif]-->' . "\n"];
return $tags;
}
@@ -291,6 +291,42 @@ class RendererBubblingTest extends RendererTestBase {
];
$data[] = [$test_element, ['bar', 'foo'], $expected_cache_items];
// Ensure that bubbleable metadata has been collected from children and set
// correctly to the main level of the render array. That ensures that correct
// bubbleable metadata exists if render array gets rendered multiple times.
$test_element = [
'#cache' => [
'keys' => ['parent'],
'tags' => ['yar', 'har']
],
'#markup' => 'parent',
'child' => [
'#render_children' => TRUE,
'subchild' => [
'#cache' => [
'contexts' => ['foo'],
'tags' => ['fiddle', 'dee'],
],
'#attached' => [
'library' => ['foo/bar']
],
'#markup' => '',
]
],
];
$expected_cache_items = [
'parent:foo' => [
'#attached' => ['library' => ['foo/bar']],
'#cache' => [
'contexts' => ['foo'],
'tags' => ['dee', 'fiddle', 'har', 'yar'],
'max-age' => Cache::PERMANENT,
],
'#markup' => 'parent',
],
];
$data[] = [$test_element, ['foo'], $expected_cache_items];
return $data;
}
@@ -65,10 +65,8 @@ class RendererTest extends RendererTestBase {
public function providerTestRenderBasic() {
$data = [];
// Part 1: the most simplistic render arrays possible, none using #theme.
// Pass a NULL.
$data[] = [NULL, ''];
// Pass an empty string.
@@ -216,7 +214,6 @@ class RendererTest extends RendererTestBase {
// Part 2: render arrays using #theme and #theme_wrappers.
// Tests that #theme and #theme_wrappers can co-exist on an element.
$build = [
'#theme' => 'common_test_foo',
@@ -302,10 +299,8 @@ class RendererTest extends RendererTestBase {
};
$data[] = [$build, '<div class="foo"></div>' . "\n", $setup_code];
// Part 3: render arrays using #markup as a fallback for #theme hooks.
// Theme suggestion is not implemented, #markup should be rendered.
$build = [
'#theme' => ['suggestionnotimplemented'],
@@ -357,10 +352,8 @@ class RendererTest extends RendererTestBase {
];
$data[] = [$build, $theme_function_output, $setup_code];
// Part 4: handling of #children and child renderable elements.
// #theme is implemented so the values of both #children and 'child' will
// be ignored - it is the responsibility of the theme hook to render these
// if appropriate.
@@ -410,6 +403,25 @@ class RendererTest extends RendererTestBase {
};
$data[] = [$build, 'baz', $setup_code];
// #theme is implemented but #render_children is TRUE. In this case the
// calling code is expecting only the children to be rendered. #prefix and
// #suffix should not be inherited for the children.
$build = [
'#theme' => 'common_test_foo',
'#children' => '',
'#prefix' => 'kangaroo',
'#suffix' => 'unicorn',
'#render_children' => TRUE,
'child' => [
'#markup' => 'kitten',
],
];
$setup_code = function () {
$this->themeManager->expects($this->never())
->method('render');
};
$data[] = [$build, 'kitten', $setup_code];
return $data;
}
@@ -569,25 +581,81 @@ class RendererTest extends RendererTestBase {
}
/**
* Tests that a first render returns the rendered output and a second doesn't.
* Tests rendering same render array twice.
*
* (Because of the #printed property.)
* Tests that a first render returns the rendered output and a second doesn't
* because of the #printed property. Also tests that correct metadata has been
* set for re-rendering.
*
* @covers ::render
* @covers ::doRender
*
* @dataProvider providerRenderTwice
*/
public function testRenderTwice() {
$build = [
'#markup' => 'test',
];
$this->assertEquals('test', $this->renderer->renderRoot($build));
public function testRenderTwice($build) {
$this->assertEquals('kittens', $this->renderer->renderRoot($build));
$this->assertEquals('kittens', $build['#markup']);
$this->assertEquals(['kittens-147'], $build['#cache']['tags']);
$this->assertTrue($build['#printed']);
// We don't want to reprint already printed render arrays.
$this->assertEquals('', $this->renderer->renderRoot($build));
}
/**
* Provides a list of render array iterations.
*
* @return array
*/
public function providerRenderTwice() {
return [
[
[
'#markup' => 'kittens',
'#cache' => [
'tags' => ['kittens-147']
],
],
],
[
[
'child' => [
'#markup' => 'kittens',
'#cache' => [
'tags' => ['kittens-147'],
],
],
],
],
[
[
'#render_children' => TRUE,
'child' => [
'#markup' => 'kittens',
'#cache' => [
'tags' => ['kittens-147'],
],
],
],
],
];
}
/**
* Ensures that #access is taken in account when rendering #render_children.
*/
public function testRenderChildrenAccess() {
$build = [
'#access' => FALSE,
'#render_children' => TRUE,
'child' => [
'#markup' => 'kittens',
],
];
$this->assertEquals('', $this->renderer->renderRoot($build));
}
/**
* Provides a list of both booleans.
*
@@ -16,7 +16,7 @@ abstract class RouteMatchTestBase extends UnitTestCase {
*
* @param $name
* Route name.
* @param Route $route
* @param \Symfony\Component\Routing\Route $route
* Request object
* @param array $parameters
* Parameters array
@@ -211,7 +211,6 @@ class UrlGeneratorTest extends UnitTestCase {
->method('processOutbound')
->with($this->anything());
// Check that the two generate methods return the same result.
$this->assertGenerateFromRoute('test_1', [], [], $url, (new BubbleableMetadata())->setCacheMaxAge(Cache::PERMANENT));
@@ -232,7 +231,6 @@ class UrlGeneratorTest extends UnitTestCase {
->method('processOutbound')
->with($this->anything());
// Check that the two generate methods return the same result.
$this->assertGenerateFromRoute('test_1', [], [], $url, (new BubbleableMetadata())->setCacheMaxAge(Cache::PERMANENT));
@@ -28,7 +28,7 @@ class SettingsTest extends UnitTestCase {
/**
* @covers ::__construct
*/
protected function setUp(){
protected function setUp() {
$this->config = [
'one' => '1',
'two' => '2',
@@ -0,0 +1,142 @@
<?php
namespace Drupal\Tests;
/**
* Makes Drupal's test API forward compatible with multiple versions of PHPUnit.
*/
trait PhpunitCompatibilityTrait {
/**
* Returns a mock object for the specified class using the available method.
*
* The getMock method does not exist in PHPUnit 6. To provide backward
* compatibility this trait provides the getMock method and uses createMock if
* this method is available on the parent class.
*
* @param string $originalClassName
* Name of the class to mock.
* @param array|null $methods
* When provided, only methods whose names are in the array are replaced
* with a configurable test double. The behavior of the other methods is not
* changed. Providing null means that no methods will be replaced.
* @param array $arguments
* Parameters to pass to the original class' constructor.
* @param string $mockClassName
* Class name for the generated test double class.
* @param bool $callOriginalConstructor
* Can be used to disable the call to the original class' constructor.
* @param bool $callOriginalClone
* Can be used to disable the call to the original class' clone constructor.
* @param bool $callAutoload
* Can be used to disable __autoload() during the generation of the test
* double class.
* @param bool $cloneArguments
* Enables the cloning of arguments passed to mocked methods.
* @param bool $callOriginalMethods
* Enables the invocation of the original methods.
* @param object $proxyTarget
* Sets the proxy target.
*
* @see \PHPUnit_Framework_TestCase::getMock
* @see https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-for-PHPUnit-5.4.0
*
* @return \PHPUnit_Framework_MockObject_MockObject
*
* @deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0.
* Use \Drupal\Tests\PhpunitCompatibilityTrait::createMock() instead.
*
* @see https://www.drupal.org/node/2907725
*/
public function getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE, $callOriginalMethods = FALSE, $proxyTarget = NULL) {
if (!$this->supports('getMock')) {
$mock = $this->getMockBuilder($originalClassName)
->setMethods($methods)
->setConstructorArgs($arguments)
->setMockClassName($mockClassName)
->setProxyTarget($proxyTarget);
if ($callOriginalConstructor) {
$mock->enableOriginalConstructor();
}
else {
$mock->disableOriginalConstructor();
}
if ($callOriginalClone) {
$mock->enableOriginalClone();
}
else {
$mock->disableOriginalClone();
}
if ($callAutoload) {
$mock->enableAutoload();
}
else {
$mock->disableAutoload();
}
if ($cloneArguments) {
$mock->enableArgumentCloning();
}
else {
$mock->disableArgumentCloning();
}
if ($callOriginalMethods) {
$mock->enableProxyingToOriginalMethods();
}
else {
$mock->disableProxyingToOriginalMethods();
}
return $mock->getMock();
}
else {
return parent::getMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, $proxyTarget);
}
}
/**
* Returns a mock object for the specified class using the available method.
*
* The createMock method does not exist in PHPUnit 4. To provide forward
* compatibility this trait provides the createMock method and uses createMock
* if this method is available on the parent class or falls back to getMock if
* it isn't.
*
* @param string $originalClassName
* Name of the class to mock.
*
* @see \PHPUnit_Framework_TestCase::getMock
*
* @return \PHPUnit_Framework_MockObject_MockObject
*/
public function createMock($originalClassName) {
if ($this->supports('createMock')) {
return parent::createMock($originalClassName);
}
else {
return $this->getMock($originalClassName, [], [], '', FALSE, FALSE);
}
}
/**
* Checks if the trait is used in a class that has a method.
*
* @param string $method
* Method to check.
*
* @return bool
* TRUE if the method is supported, FALSE if not.
*/
private function supports($method) {
// Get the parent class of the currently running test class.
$parent = get_parent_class($this);
// Ensure that the method_exists() check on the createMock method is carried
// out on the first parent of $this that does not have access to this
// trait's methods. This is because the trait also has a method called
// createMock(). Most often the check will be made on
// \PHPUnit\Framework\TestCase.
while (method_exists($parent, 'supports')) {
$parent = get_parent_class($parent);
}
return method_exists($parent, $method);
}
}
@@ -0,0 +1,115 @@
<?php
namespace Drupal\Tests;
/**
* Tests the PHPUnit forward compatibility trait.
*
* @coversDefaultClass \Drupal\Tests\PhpunitCompatibilityTrait
* @group Tests
*/
class PhpunitCompatibilityTraitTest extends UnitTestCase {
/**
* Tests that getMock is available and calls the correct parent method.
*
* @covers ::getMock
* @dataProvider providerMockVersions
*/
public function testGetMock($className, $expected) {
$class = new $className();
$this->assertSame($expected, $class->getMock($this->randomMachineName()));
}
/**
* Tests that createMock is available and calls the correct parent method.
*
* @covers ::createMock
* @dataProvider providerMockVersions
*/
public function testCreateMock($className, $expected) {
$class = new $className();
$this->assertSame($expected, $class->createMock($this->randomMachineName()));
}
/**
* Returns the class names and the string they return.
*
* @return array
*/
public function providerMockVersions() {
return [
[UnitTestCasePhpunit4TestClass::class, 'PHPUnit 4'],
[UnitTestCasePhpunit4TestClassExtends::class, 'PHPUnit 4'],
[UnitTestCasePhpunit6TestClass::class, 'PHPUnit 6'],
[UnitTestCasePhpunit6TestClassExtends::class, 'PHPUnit 6'],
];
}
}
/**
* Test class for \PHPUnit\Framework\TestCase in PHPUnit 4.
*/
class Phpunit4TestClass {
public function getMock($originalClassName) {
return 'PHPUnit 4';
}
}
/**
* Test class for \PHPUnit\Framework\TestCase in PHPUnit 6.
*/
class Phpunit6TestClass {
public function createMock($originalClassName) {
return 'PHPUnit 6';
}
public function getMockbuilder() {
return new Mockbuilder();
}
}
/**
* Test double for PHPUnit_Framework_MockObject_MockBuilder.
*/
class Mockbuilder {
public function __call($name, $arguments) {
return $this;
}
public function getMock() {
return 'PHPUnit 6';
}
}
/**
* Test class for \Drupal\Tests\UnitTestCase with PHPUnit 4.
*/
class UnitTestCasePhpunit4TestClass extends Phpunit4TestClass {
use PhpunitCompatibilityTrait;
}
/**
* Test class for \Drupal\Tests\UnitTestCase with PHPUnit 4.
*/
class UnitTestCasePhpunit4TestClassExtends extends UnitTestCasePhpunit4TestClass {
}
/**
* Test class for \Drupal\Tests\UnitTestCase with PHPUnit 6.
*/
class UnitTestCasePhpunit6TestClass extends Phpunit6TestClass {
use PhpunitCompatibilityTrait;
}
/**
* Test class for \Drupal\Tests\UnitTestCase with PHPUnit 6.
*/
class UnitTestCasePhpunit6TestClassExtends extends UnitTestCasePhpunit6TestClass {
}
@@ -164,7 +164,8 @@ trait TestFileCreationTrait {
}
// Create filename.
file_put_contents('public://' . $filename . '.txt', $text);
$filename = 'public://' . $filename . '.txt';
file_put_contents($filename, $text);
return $filename;
}
+7 -5
View File
@@ -17,6 +17,8 @@ use PHPUnit\Framework\TestCase;
*/
abstract class UnitTestCase extends TestCase {
use PhpunitCompatibilityTrait;
/**
* The random generator.
*
@@ -135,7 +137,7 @@ abstract class UnitTestCase extends TestCase {
}
// Construct a config factory with the array of configuration object stubs
// as its return map.
$config_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface');
$config_factory = $this->createMock('Drupal\Core\Config\ConfigFactoryInterface');
$config_factory->expects($this->any())
->method('get')
->will($this->returnValueMap($config_get_map));
@@ -157,7 +159,7 @@ abstract class UnitTestCase extends TestCase {
* A mocked config storage.
*/
public function getConfigStorageStub(array $configs) {
$config_storage = $this->getMock('Drupal\Core\Config\NullStorage');
$config_storage = $this->createMock('Drupal\Core\Config\NullStorage');
$config_storage->expects($this->any())
->method('listAll')
->will($this->returnValue(array_keys($configs)));
@@ -204,7 +206,7 @@ abstract class UnitTestCase extends TestCase {
* A mock translation object.
*/
public function getStringTranslationStub() {
$translation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface');
$translation = $this->createMock('Drupal\Core\StringTranslation\TranslationInterface');
$translation->expects($this->any())
->method('translate')
->willReturnCallback(function ($string, array $args = [], array $options = []) use ($translation) {
@@ -234,7 +236,7 @@ abstract class UnitTestCase extends TestCase {
* The container with the cache tags invalidator service.
*/
protected function getContainerWithCacheTagsInvalidator(CacheTagsInvalidatorInterface $cache_tags_validator) {
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->createMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container->expects($this->any())
->method('get')
->with('cache_tags.invalidator')
@@ -251,7 +253,7 @@ abstract class UnitTestCase extends TestCase {
* The class resolver stub.
*/
protected function getClassResolverStub() {
$class_resolver = $this->getMock('Drupal\Core\DependencyInjection\ClassResolverInterface');
$class_resolver = $this->createMock('Drupal\Core\DependencyInjection\ClassResolverInterface');
$class_resolver->expects($this->any())
->method('getInstanceFromDefinition')
->will($this->returnCallback(function ($class) {
+1 -1
View File
@@ -451,7 +451,7 @@ class WebAssert extends MinkWebAssert {
* @throws \Behat\Mink\Exception\ElementNotFoundException
* @throws \Behat\Mink\Exception\ExpectationException
*/
public function fieldDisabled($field, TraversableElement $container = NULL) {
public function fieldDisabled($field, TraversableElement $container = NULL) {
$container = $container ?: $this->session->getPage();
$node = $container->findField($field);