Update to Drupal 8.0.0-beta15. For more information, see: https://www.drupal.org/node/2563023

This commit is contained in:
Pantheon Automation 2015-09-04 13:20:09 -07:00 committed by Greg Anderson
parent 2720a9ec4b
commit f3791f1da3
1898 changed files with 54300 additions and 11481 deletions

View file

@ -11,6 +11,7 @@ use Drupal\Core\Access\AccessCheckInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\AccessManagerInterface;
use Drupal\Core\Access\CheckProvider;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Drupal\Core\Routing\RouteMatch;
use Drupal\Core\Access\AccessManager;
use Drupal\Core\Access\DefaultAccessCheck;
@ -94,6 +95,9 @@ class AccessManagerTest extends UnitTestCase {
parent::setUp();
$this->container = new ContainerBuilder();
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class)->reveal();
$this->container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($this->container);
$this->routeCollection = new RouteCollection();
$this->routeCollection->add('test_route_1', new Route('/test-route-1'));

View file

@ -52,7 +52,6 @@ class AccessResultTest extends UnitTestCase {
/**
* Tests the construction of an AccessResult object.
*
* @covers ::__construct
* @covers ::neutral
*/
public function testConstruction() {
@ -852,8 +851,15 @@ class AccessResultTest extends UnitTestCase {
* @covers ::allowedIfHasPermissions
*
* @dataProvider providerTestAllowedIfHasPermissions
*
* @param string[] $permissions
* The permissions to check for.
* @param string $conjunction
* The conjunction to use when checking for permission. 'AND' or 'OR'.
* @param \Drupal\Core\Access\AccessResult $expected_access
* The expected access check result.
*/
public function testAllowedIfHasPermissions($permissions, $conjunction, $expected_access) {
public function testAllowedIfHasPermissions($permissions, $conjunction, AccessResult $expected_access) {
$account = $this->getMock('\Drupal\Core\Session\AccountInterface');
$account->expects($this->any())
->method('hasPermission')
@ -862,6 +868,10 @@ class AccessResultTest extends UnitTestCase {
['denied', FALSE],
]);
if ($permissions) {
$expected_access->cachePerPermissions();
}
$access_result = AccessResult::allowedIfHasPermissions($account, $permissions, $conjunction);
$this->assertEquals($expected_access, $access_result);
}
@ -875,14 +885,14 @@ class AccessResultTest extends UnitTestCase {
return [
[[], 'AND', AccessResult::allowedIf(FALSE)],
[[], 'OR', AccessResult::allowedIf(FALSE)],
[['allowed'], 'OR', AccessResult::allowedIf(TRUE)->addCacheContexts(['user.permissions'])],
[['allowed'], 'AND', AccessResult::allowedIf(TRUE)->addCacheContexts(['user.permissions'])],
[['denied'], 'OR', AccessResult::allowedIf(FALSE)->addCacheContexts(['user.permissions'])],
[['denied'], 'AND', AccessResult::allowedIf(FALSE)->addCacheContexts(['user.permissions'])],
[['allowed', 'denied'], 'OR', AccessResult::allowedIf(TRUE)->addCacheContexts(['user.permissions'])],
[['denied', 'allowed'], 'OR', AccessResult::allowedIf(TRUE)->addCacheContexts(['user.permissions'])],
[['allowed', 'denied', 'other'], 'OR', AccessResult::allowedIf(TRUE)->addCacheContexts(['user.permissions'])],
[['allowed', 'denied'], 'AND', AccessResult::allowedIf(FALSE)->addCacheContexts(['user.permissions'])],
[['allowed'], 'OR', AccessResult::allowedIf(TRUE)],
[['allowed'], 'AND', AccessResult::allowedIf(TRUE)],
[['denied'], 'OR', AccessResult::allowedIf(FALSE)],
[['denied'], 'AND', AccessResult::allowedIf(FALSE)],
[['allowed', 'denied'], 'OR', AccessResult::allowedIf(TRUE)],
[['denied', 'allowed'], 'OR', AccessResult::allowedIf(TRUE)],
[['allowed', 'denied', 'other'], 'OR', AccessResult::allowedIf(TRUE)],
[['allowed', 'denied'], 'AND', AccessResult::allowedIf(FALSE)],
];
}

View file

@ -38,7 +38,6 @@ class CssCollectionGrouperUnitTest extends UnitTestCase {
$css_assets = array(
'system.base.css' => array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.012,
'media' => 'all',
@ -49,7 +48,6 @@ class CssCollectionGrouperUnitTest extends UnitTestCase {
),
'system.theme.css' => array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.013,
'media' => 'all',
@ -62,7 +60,6 @@ class CssCollectionGrouperUnitTest extends UnitTestCase {
'group' => -100,
'type' => 'file',
'weight' => 0.004,
'every_page' => FALSE,
'media' => 'all',
'preprocess' => TRUE,
'data' => 'core/misc/ui/themes/base/jquery.ui.core.css',
@ -70,7 +67,6 @@ class CssCollectionGrouperUnitTest extends UnitTestCase {
'basename' => 'jquery.ui.core.css',
),
'field.css' => array(
'every_page' => TRUE,
'group' => 0,
'type' => 'file',
'weight' => 0.011,
@ -81,7 +77,6 @@ class CssCollectionGrouperUnitTest extends UnitTestCase {
'basename' => 'field.css',
),
'external.css' => array(
'every_page' => FALSE,
'group' => 0,
'type' => 'external',
'weight' => 0.009,
@ -93,7 +88,6 @@ class CssCollectionGrouperUnitTest extends UnitTestCase {
),
'elements.css' => array(
'group' => 100,
'every_page' => TRUE,
'media' => 'all',
'type' => 'file',
'weight' => 0.001,
@ -104,7 +98,6 @@ class CssCollectionGrouperUnitTest extends UnitTestCase {
),
'print.css' => array(
'group' => 100,
'every_page' => TRUE,
'media' => 'print',
'type' => 'file',
'weight' => 0.003,
@ -117,62 +110,53 @@ class CssCollectionGrouperUnitTest extends UnitTestCase {
$groups = $this->grouper->group($css_assets);
$this->assertSame(count($groups), 6, "6 groups created.");
$this->assertSame(count($groups), 5, "5 groups created.");
// Check group 1.
$this->assertSame($groups[0]['group'], -100);
$this->assertSame($groups[0]['every_page'], TRUE);
$this->assertSame($groups[0]['type'], 'file');
$this->assertSame($groups[0]['media'], 'all');
$this->assertSame($groups[0]['preprocess'], TRUE);
$this->assertSame(count($groups[0]['items']), 2);
$this->assertContains($css_assets['system.base.css'], $groups[0]['items']);
$this->assertContains($css_assets['system.theme.css'], $groups[0]['items']);
$group = $groups[0];
$this->assertSame($group['group'], -100);
$this->assertSame($group['type'], 'file');
$this->assertSame($group['media'], 'all');
$this->assertSame($group['preprocess'], TRUE);
$this->assertSame(count($group['items']), 3);
$this->assertContains($css_assets['system.base.css'], $group['items']);
$this->assertContains($css_assets['system.theme.css'], $group['items']);
// Check group 2.
$this->assertSame($groups[1]['group'], -100);
$this->assertSame($groups[1]['every_page'], FALSE);
$this->assertSame($groups[1]['type'], 'file');
$this->assertSame($groups[1]['media'], 'all');
$this->assertSame($groups[1]['preprocess'], TRUE);
$this->assertSame(count($groups[1]['items']), 1);
$this->assertContains($css_assets['jquery.ui.core.css'], $groups[1]['items']);
$group = $groups[1];
$this->assertSame($group['group'], 0);
$this->assertSame($group['type'], 'file');
$this->assertSame($group['media'], 'all');
$this->assertSame($group['preprocess'], TRUE);
$this->assertSame(count($group['items']), 1);
$this->assertContains($css_assets['field.css'], $group['items']);
// Check group 3.
$this->assertSame($groups[2]['group'], 0);
$this->assertSame($groups[2]['every_page'], TRUE);
$this->assertSame($groups[2]['type'], 'file');
$this->assertSame($groups[2]['media'], 'all');
$this->assertSame($groups[2]['preprocess'], TRUE);
$this->assertSame(count($groups[2]['items']), 1);
$this->assertContains($css_assets['field.css'], $groups[2]['items']);
$group = $groups[2];
$this->assertSame($group['group'], 0);
$this->assertSame($group['type'], 'external');
$this->assertSame($group['media'], 'all');
$this->assertSame($group['preprocess'], TRUE);
$this->assertSame(count($group['items']), 1);
$this->assertContains($css_assets['external.css'], $group['items']);
// Check group 4.
$this->assertSame($groups[3]['group'], 0);
$this->assertSame($groups[3]['every_page'], FALSE);
$this->assertSame($groups[3]['type'], 'external');
$this->assertSame($groups[3]['media'], 'all');
$this->assertSame($groups[3]['preprocess'], TRUE);
$this->assertSame(count($groups[3]['items']), 1);
$this->assertContains($css_assets['external.css'], $groups[3]['items']);
$group = $groups[3];
$this->assertSame($group['group'], 100);
$this->assertSame($group['type'], 'file');
$this->assertSame($group['media'], 'all');
$this->assertSame($group['preprocess'], TRUE);
$this->assertSame(count($group['items']), 1);
$this->assertContains($css_assets['elements.css'], $group['items']);
// Check group 5.
$this->assertSame($groups[4]['group'], 100);
$this->assertSame($groups[4]['every_page'], TRUE);
$this->assertSame($groups[4]['type'], 'file');
$this->assertSame($groups[4]['media'], 'all');
$this->assertSame($groups[4]['preprocess'], TRUE);
$this->assertSame(count($groups[4]['items']), 1);
$this->assertContains($css_assets['elements.css'], $groups[4]['items']);
// Check group 6.
$this->assertSame($groups[5]['group'], 100);
$this->assertSame($groups[5]['every_page'], TRUE);
$this->assertSame($groups[5]['type'], 'file');
$this->assertSame($groups[5]['media'], 'print');
$this->assertSame($groups[5]['preprocess'], TRUE);
$this->assertSame(count($groups[5]['items']), 1);
$this->assertContains($css_assets['print.css'], $groups[5]['items']);
$group = $groups[4];
$this->assertSame($group['group'], 100);
$this->assertSame($group['type'], 'file');
$this->assertSame($group['media'], 'print');
$this->assertSame($group['preprocess'], TRUE);
$this->assertSame(count($group['items']), 1);
$this->assertContains($css_assets['print.css'], $group['items']);
}
}

View file

@ -71,7 +71,6 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
$this->renderer = new CssCollectionRenderer($this->state);
$this->fileCssGroup = array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'media' => 'all',
'preprocess' => TRUE,
@ -79,7 +78,6 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
'items' => array(
0 => array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.012,
'media' => 'all',
@ -90,7 +88,6 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
),
1 => array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.013,
'media' => 'all',
@ -121,7 +118,7 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
'#browsers' => $browsers,
);
};
$create_style_element = function($value, $media, $browsers = array(), $wrap_in_cdata = FALSE) {
$create_style_element = function($value, $media, $browsers = array()) {
$style_element = array(
'#type' => 'html_tag',
'#tag' => 'style',
@ -131,15 +128,11 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
),
'#browsers' => $browsers,
);
if ($wrap_in_cdata) {
$style_element['#value_prefix'] = "\n/* <![CDATA[ */\n";
$style_element['#value_suffix'] = "\n/* ]]> */\n";
}
return $style_element;
};
$create_file_css_asset = function($data, $media = 'all', $preprocess = TRUE) {
return array('group' => 0, 'every_page' => FALSE, 'type' => 'file', 'media' => $media, 'preprocess' => $preprocess, 'data' => $data, 'browsers' => array());
return array('group' => 0, 'type' => 'file', 'media' => $media, 'preprocess' => $preprocess, 'data' => $data, 'browsers' => array());
};
return array(
@ -147,7 +140,7 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
0 => array(
// CSS assets.
array(
0 => array('group' => 0, 'every_page' => TRUE, 'type' => 'external', 'media' => 'all', 'preprocess' => TRUE, 'data' => 'http://example.com/popular.js', 'browsers' => array()),
0 => array('group' => 0, 'type' => 'external', 'media' => 'all', 'preprocess' => TRUE, 'data' => 'http://example.com/popular.js', 'browsers' => array()),
),
// Render elements.
array(
@ -157,10 +150,10 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
// Single file CSS asset.
2 => array(
array(
0 => array('group' => 0, 'every_page' => TRUE, 'type' => 'file', 'media' => 'all', 'preprocess' => TRUE, 'data' => 'public://css/file-every_page-all', 'browsers' => array()),
0 => array('group' => 0, 'type' => 'file', 'media' => 'all', 'preprocess' => TRUE, 'data' => 'public://css/file-all', 'browsers' => array()),
),
array(
0 => $create_link_element(file_create_url('public://css/file-every_page-all') . '?0', 'all'),
0 => $create_link_element(file_create_url('public://css/file-all') . '?0', 'all'),
),
),
// 31 file CSS assets: expect 31 link elements.
@ -494,7 +487,6 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
$css_group = array(
'group' => 0,
'every_page' => TRUE,
'type' => 'internal',
'media' => 'all',
'preprocess' => TRUE,

View file

@ -74,7 +74,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
array(
array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.012,
'media' => 'all',
@ -95,7 +94,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
array(
array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.013,
'media' => 'all',
@ -111,7 +109,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
array(
array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.013,
'media' => 'all',
@ -129,7 +126,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
array(
array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.013,
'media' => 'all',
@ -146,7 +142,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
array(
array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.013,
'media' => 'all',
@ -160,7 +155,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
array(
array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.013,
'media' => 'all',
@ -174,7 +168,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
array(
array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.013,
'media' => 'all',
@ -188,7 +181,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
array(
array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.013,
'media' => 'all',
@ -202,7 +194,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
array(
array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.013,
'media' => 'all',
@ -216,7 +207,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
array(
array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.013,
'media' => 'all',
@ -247,7 +237,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
$css_asset = array(
'group' => -100,
'every_page' => TRUE,
'type' => 'file',
'weight' => 0.012,
'media' => 'all',
@ -268,7 +257,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
$css_asset = array(
'group' => -100,
'every_page' => TRUE,
// Type external.
'type' => 'external',
'weight' => 0.012,

View file

@ -7,7 +7,9 @@
namespace Drupal\Tests\Core\Breadcrumb;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Breadcrumb\BreadcrumbManager;
use Drupal\Core\Cache\Cache;
use Drupal\Tests\UnitTestCase;
/**
@ -16,6 +18,13 @@ use Drupal\Tests\UnitTestCase;
*/
class BreadcrumbManagerTest extends UnitTestCase {
/**
* The breadcrumb object.
*
* @var \Drupal\Core\Breadcrumb\Breadcrumb
*/
protected $breadcrumb;
/**
* The tested breadcrumb manager.
*
@ -36,14 +45,23 @@ class BreadcrumbManagerTest extends UnitTestCase {
protected function setUp() {
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->breadcrumbManager = new BreadcrumbManager($this->moduleHandler);
$this->breadcrumb = new Breadcrumb();
}
/**
* Tests the breadcrumb manager without any set breadcrumb.
*/
public function testBuildWithoutBuilder() {
$result = $this->breadcrumbManager->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
$this->assertEquals(array(), $result);
$route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
$this->moduleHandler->expects($this->once())
->method('alter')
->with('system_breadcrumb', $this->breadcrumb, $route_match, ['builder' => NULL]);
$breadcrumb = $this->breadcrumbManager->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
$this->assertEquals([], $breadcrumb->getLinks());
$this->assertEquals([], $breadcrumb->getCacheContexts());
$this->assertEquals([], $breadcrumb->getCacheTags());
$this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
}
/**
@ -51,7 +69,9 @@ class BreadcrumbManagerTest extends UnitTestCase {
*/
public function testBuildWithSingleBuilder() {
$builder = $this->getMock('Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface');
$breadcrumb = array('<a href="/example">Test</a>');
$links = array('<a href="/example">Test</a>');
$this->breadcrumb->setLinks($links);
$this->breadcrumb->setCacheContexts(['foo'])->setCacheTags(['bar']);
$builder->expects($this->once())
->method('applies')
@ -59,17 +79,20 @@ class BreadcrumbManagerTest extends UnitTestCase {
$builder->expects($this->once())
->method('build')
->will($this->returnValue($breadcrumb));
->willReturn($this->breadcrumb);
$route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
$this->moduleHandler->expects($this->once())
->method('alter')
->with('system_breadcrumb', $breadcrumb, $route_match, array('builder' => $builder));
->with('system_breadcrumb', $this->breadcrumb, $route_match, array('builder' => $builder));
$this->breadcrumbManager->addBuilder($builder, 0);
$result = $this->breadcrumbManager->build($route_match);
$this->assertEquals($breadcrumb, $result);
$breadcrumb = $this->breadcrumbManager->build($route_match);
$this->assertEquals($links, $breadcrumb->getLinks());
$this->assertEquals(['foo'], $breadcrumb->getCacheContexts());
$this->assertEquals(['bar'], $breadcrumb->getCacheTags());
$this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
}
/**
@ -83,25 +106,30 @@ class BreadcrumbManagerTest extends UnitTestCase {
->method('build');
$builder2 = $this->getMock('Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface');
$breadcrumb2 = array('<a href="/example2">Test2</a>');
$links2 = array('<a href="/example2">Test2</a>');
$this->breadcrumb->setLinks($links2);
$this->breadcrumb->setCacheContexts(['baz'])->setCacheTags(['qux']);
$builder2->expects($this->once())
->method('applies')
->will($this->returnValue(TRUE));
$builder2->expects($this->once())
->method('build')
->will($this->returnValue($breadcrumb2));
->willReturn($this->breadcrumb);
$route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
$this->moduleHandler->expects($this->once())
->method('alter')
->with('system_breadcrumb', $breadcrumb2, $route_match, array('builder' => $builder2));
->with('system_breadcrumb', $this->breadcrumb, $route_match, array('builder' => $builder2));
$this->breadcrumbManager->addBuilder($builder1, 0);
$this->breadcrumbManager->addBuilder($builder2, 10);
$result = $this->breadcrumbManager->build($route_match);
$this->assertEquals($breadcrumb2, $result);
$breadcrumb = $this->breadcrumbManager->build($route_match);
$this->assertEquals($links2, $breadcrumb->getLinks());
$this->assertEquals(['baz'], $breadcrumb->getCacheContexts());
$this->assertEquals(['qux'], $breadcrumb->getCacheTags());
$this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
}
/**
@ -116,25 +144,30 @@ class BreadcrumbManagerTest extends UnitTestCase {
->method('build');
$builder2 = $this->getMock('Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface');
$breadcrumb2 = array('<a href="/example2">Test2</a>');
$links2 = ['<a href="/example2">Test2</a>'];
$this->breadcrumb->setLinks($links2);
$this->breadcrumb->setCacheContexts(['baz'])->setCacheTags(['qux']);
$builder2->expects($this->once())
->method('applies')
->will($this->returnValue(TRUE));
$builder2->expects($this->once())
->method('build')
->will($this->returnValue($breadcrumb2));
->willReturn($this->breadcrumb);
$route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
$this->moduleHandler->expects($this->once())
->method('alter')
->with('system_breadcrumb', $breadcrumb2, $route_match, array('builder' => $builder2));
->with('system_breadcrumb', $this->breadcrumb, $route_match, array('builder' => $builder2));
$this->breadcrumbManager->addBuilder($builder1, 10);
$this->breadcrumbManager->addBuilder($builder2, 0);
$result = $this->breadcrumbManager->build($route_match);
$this->assertEquals($breadcrumb2, $result);
$breadcrumb = $this->breadcrumbManager->build($route_match);
$this->assertEquals($links2, $breadcrumb->getLinks());
$this->assertEquals(['baz'], $breadcrumb->getCacheContexts());
$this->assertEquals(['qux'], $breadcrumb->getCacheTags());
$this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
}
/**

View file

@ -0,0 +1,32 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Breadcrumb\BreadcrumbTest.
*/
namespace Drupal\Tests\Core\Breadcrumb;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Breadcrumb\Breadcrumb
* @group Breadcrumb
*/
class BreadcrumbTest extends UnitTestCase {
/**
* @covers ::setLinks
* @expectedException \LogicException
* @expectedExceptionMessage Once breadcrumb links are set, only additional breadcrumb links can be added.
*/
public function testSetLinks() {
$breadcrumb = new Breadcrumb();
$breadcrumb->setLinks([new Link('Home', Url::fromRoute('<front>'))]);
$breadcrumb->setLinks([new Link('None', Url::fromRoute('<none>'))]);
}
}

View file

@ -19,6 +19,8 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Psr\Http\Message\ServerRequestInterface;
/**
* @coversDefaultClass \Drupal\Core\Controller\ControllerResolver
@ -40,6 +42,13 @@ class ControllerResolverTest extends UnitTestCase {
*/
protected $container;
/**
* The PSR-7 converter.
*
* @var \Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface
*/
protected $httpMessageFactory;
/**
* {@inheritdoc}
*/
@ -49,7 +58,8 @@ class ControllerResolverTest extends UnitTestCase {
$this->container = new ContainerBuilder();
$class_resolver = new ClassResolver();
$class_resolver->setContainer($this->container);
$this->controllerResolver = new ControllerResolver($class_resolver);
$this->httpMessageFactory = new DiactorosFactory();
$this->controllerResolver = new ControllerResolver($this->httpMessageFactory, $class_resolver);
}
/**
@ -61,7 +71,7 @@ class ControllerResolverTest extends UnitTestCase {
* @see \Drupal\Core\Controller\ControllerResolver::doGetArguments()
*/
public function testGetArguments() {
$controller = function(EntityInterface $entity, $user, RouteMatchInterface $route_match) {
$controller = function(EntityInterface $entity, $user, RouteMatchInterface $route_match, ServerRequestInterface $psr_7) {
};
$mock_entity = $this->getMockBuilder('Drupal\Core\Entity\Entity')
->disableOriginalConstructor()
@ -71,12 +81,13 @@ class ControllerResolverTest extends UnitTestCase {
'entity' => $mock_entity,
'user' => $mock_account,
'_raw_variables' => new ParameterBag(array('entity' => 1, 'user' => 1)),
));
), array(), array(), array('HTTP_HOST' => 'drupal.org'));
$arguments = $this->controllerResolver->getArguments($request, $controller);
$this->assertEquals($mock_entity, $arguments[0]);
$this->assertEquals($mock_account, $arguments[1]);
$this->assertEquals(RouteMatch::createFromRequest($request), $arguments[2], 'Ensure that the route match object is passed along as well');
$this->assertInstanceOf(ServerRequestInterface::class, $arguments[3], 'Ensure that the PSR-7 object is passed along as well');
}
/**
@ -219,6 +230,20 @@ class ControllerResolverTest extends UnitTestCase {
$this->assertEquals([RouteMatch::createFromRequest($request), $request], $arguments);
}
/**
* Tests getArguments with a route match and a PSR-7 request.
*
* @covers ::getArguments
* @covers ::doGetArguments
*/
public function testGetArgumentsWithRouteMatchAndPsr7Request() {
$request = Request::create('/test');
$mock_controller = new MockControllerPsr7();
$arguments = $this->controllerResolver->getArguments($request, [$mock_controller, 'getControllerWithRequestAndRouteMatch']);
$this->assertEquals(RouteMatch::createFromRequest($request), $arguments[0], 'Ensure that the route match object is passed along as well');
$this->assertInstanceOf('Psr\Http\Message\ServerRequestInterface', $arguments[1], 'Ensure that the PSR-7 object is passed along as well');
}
}
class MockController {
@ -231,6 +256,17 @@ class MockController {
}
}
class MockControllerPsr7 {
public function getResult() {
return ['#markup' => 'This is a regular controller'];
}
public function getControllerWithRequestAndRouteMatch(RouteMatchInterface $route_match, ServerRequestInterface $request) {
return ['#markup' => 'this is another example controller'];
}
}
class MockContainerInjection implements ContainerInjectionInterface {
protected $result;
public function __construct($result) {

View file

@ -7,7 +7,6 @@
namespace Drupal\Tests\Core\Controller;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Controller\TitleResolver;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\ParameterBag;
@ -151,7 +150,7 @@ class TitleCallback {
* Returns the example string.
*/
public function example($value) {
return SafeMarkup::format('test @value', array('@value' => $value));
return 'test ' . $value;
}
}

View file

@ -254,12 +254,12 @@ class ConnectionTest extends UnitTestCase {
array(''),
),
array(
'/* Exploit * / DROP TABLE node; -- */ ',
'/* Exploit * / DROP TABLE node; -- */ ',
array('Exploit * / DROP TABLE node; --'),
),
array(
'/* Exploit DROP TABLE node; --; another comment */ ',
array('Exploit */ DROP TABLE node; --', 'another comment'),
'/* Exploit * / DROP TABLE node; --; another comment */ ',
array('Exploit * / DROP TABLE node; --', 'another comment'),
),
);
}
@ -286,8 +286,8 @@ class ConnectionTest extends UnitTestCase {
public function providerFilterComments() {
return array(
array('', ''),
array('Exploit * / DROP TABLE node; --', 'Exploit * / DROP TABLE node; --'),
array('Exploit DROP TABLE node; --', 'Exploit */ DROP TABLE node; --'),
array('Exploit * / DROP TABLE node; --', 'Exploit * / DROP TABLE node; --'),
array('Exploit * / DROP TABLE node; --', 'Exploit */ DROP TABLE node; --'),
);
}

View file

@ -0,0 +1,81 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Database\Driver\pgsql\PostgresqlSchemaTest.
*/
namespace Drupal\Tests\Core\Database\Driver\pgsql;
use Drupal\Core\Database\Driver\pgsql\Schema;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Database\Driver\pgsql\Schema
* @group Database
*/
class PostgresqlSchemaTest extends UnitTestCase {
/**
* The PostgreSql DB connection.
*
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Database\Driver\pgsql\Connection
*/
protected $connection;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->connection = $this->getMockBuilder('\Drupal\Core\Database\Driver\pgsql\Connection')
->disableOriginalConstructor()
->getMock();
}
/**
* Tests whether the actual constraint name is correctly computed.
*
* @param string $table_name
* The table name the constrained column belongs to.
* @param string $name
* The constraint name.
* @param string $expected
* The expected computed constraint name.
*
* @covers ::constraintExists
* @dataProvider providerComputedConstraintName
*/
public function testComputedConstraintName($table_name, $name, $expected) {
$max_identifier_length = 63;
$schema = new Schema($this->connection);
$statement = $this->getMock('\Drupal\Core\Database\StatementInterface');
$statement->expects($this->any())
->method('fetchField')
->willReturn($max_identifier_length);
$this->connection->expects($this->any())
->method('query')
->willReturn($statement);
$this->connection->expects($this->at(2))
->method('query')
->with("SELECT 1 FROM pg_constraint WHERE conname = '$expected'")
->willReturn($this->getMock('\Drupal\Core\Database\StatementInterface'));
$schema->constraintExists($table_name, $name);
}
/**
* Data provider for ::testComputedConstraintName().
*/
public function providerComputedConstraintName() {
return [
['user_field_data', 'pkey', 'user_field_data____pkey'],
['user_field_data', 'name__key', 'user_field_data__name__key'],
['user_field_data', 'a_veeeery_veery_very_super_long_field_name__key', 'drupal_BGGYAXgbqlAF1rMOyFTdZGj9zIMXZtSvEjMAKZ9wGIk_key'],
];
}
}

View file

@ -169,7 +169,7 @@ class DateTest extends UnitTestCase {
*/
public function testGetSampleDateFormats() {
$timestamp = strtotime('2015-03-22 14:23:00');
$expected = $this->dateFormatter->getSampleDateFormats('en', $timestamp, 'Europe/London');
$expected = $this->dateFormatter->getSampleDateFormats('en', $timestamp, 'Australia/Sydney');
// Removed characters related to timezone 'e' and 'T', as test does not have
// timezone set.

View file

@ -70,4 +70,14 @@ class ContainerBuilderTest extends UnitTestCase {
$container->register('Bar');
}
/**
* Tests serialization.
*
* @expectedException \AssertionError
*/
public function testSerialize() {
$container = new ContainerBuilder();
serialize($container);
}
}

View file

@ -20,7 +20,7 @@ class ContainerTest extends UnitTestCase {
/**
* Tests serialization.
*
* @expectedException \PHPUnit_Framework_Error
* @expectedException \AssertionError
*/
public function testSerialize() {
$container = new Container();

View file

@ -46,14 +46,20 @@ class DiscoverServiceProvidersTest extends UnitTestCase {
/**
* Tests the exception when container_yamls is not set.
*
* @covers ::discoverServiceProviders
* @expectedException \Exception
*/
public function testDiscoverServiceNoContainerYamls() {
new Settings([]);
$kernel = new DrupalKernel('prod', new \Composer\Autoload\ClassLoader());
$kernel->discoverServiceProviders();
$expect = [
'app' => [
'core' => 'core/core.services.yml',
],
'site' => [
],
];
$this->assertAttributeSame($expect, 'serviceYamls', $kernel);
}
}

View file

@ -7,6 +7,11 @@
namespace Drupal\Tests\Core\Entity;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Drupal\Core\DependencyInjection\Container;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\Routing\Route;
use Drupal\Core\Access\AccessResult;
@ -16,32 +21,67 @@ use Drupal\Tests\UnitTestCase;
/**
* Unit test of entity access checking system.
*
* @coversDefaultClass \Drupal\Core\Entity\EntityAccessCheck
*
* @group Access
* @group Entity
*/
class EntityAccessCheckTest extends UnitTestCase {
/**
* {@inheritdoc}
*/
protected function setUp() {
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class)->reveal();
$container = new Container();
$container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($container);
}
/**
* Tests the method for checking access to routes.
*/
public function testAccess() {
$route = new Route('/foo', array(), array('_entity_access' => 'node.update'));
$upcasted_arguments = new ParameterBag();
$route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
$route_match->expects($this->once())
->method('getParameters')
->will($this->returnValue($upcasted_arguments));
$node = $this->getMockBuilder('Drupal\node\Entity\Node')
->disableOriginalConstructor()
->getMock();
$node->expects($this->any())
->method('access')
->will($this->returnValue(AccessResult::allowed()->cachePerPermissions()));
$route = new Route('/foo/{var_name}', [], ['_entity_access' => 'var_name.update'], ['parameters' => ['var_name' => ['type' => 'entity:node']]]);
/** @var \Drupal\Core\Session\AccountInterface $account */
$account = $this->prophesize(AccountInterface::class)->reveal();
/** @var \Drupal\node\NodeInterface|\Prophecy\Prophecy\ObjectProphecy $route_match */
$node = $this->prophesize(NodeInterface::class);
$node->access('update', $account, TRUE)->willReturn(AccessResult::allowed());
$node = $node->reveal();
/** @var \Drupal\Core\Routing\RouteMatchInterface|\Prophecy\Prophecy\ObjectProphecy $route_match */
$route_match = $this->prophesize(RouteMatchInterface::class);
$route_match->getRawParameters()->willReturn(new ParameterBag(['var_name' => 1]));
$route_match->getParameters()->willReturn(new ParameterBag(['var_name' => $node]));
$route_match = $route_match->reveal();
$access_check = new EntityAccessCheck();
$upcasted_arguments->set('node', $node);
$account = $this->getMock('Drupal\Core\Session\AccountInterface');
$access = $access_check->access($route, $route_match, $account);
$this->assertEquals(AccessResult::allowed()->cachePerPermissions(), $access);
$this->assertEquals(AccessResult::allowed(), $access_check->access($route, $route_match, $account));
}
/**
* @covers ::access
*/
public function testAccessWithTypePlaceholder() {
$route = new Route('/foo/{entity_type}/{var_name}', [], ['_entity_access' => 'var_name.update'], ['parameters' => ['var_name' => ['type' => 'entity:{entity_type}']]]);
/** @var \Drupal\Core\Session\AccountInterface $account */
$account = $this->prophesize(AccountInterface::class)->reveal();
/** @var \Drupal\node\NodeInterface|\Prophecy\Prophecy\ObjectProphecy $node */
$node = $this->prophesize(NodeInterface::class);
$node->access('update', $account, TRUE)->willReturn(AccessResult::allowed());
$node = $node->reveal();
/** @var \Drupal\Core\Routing\RouteMatchInterface|\Prophecy\Prophecy\ObjectProphecy $route_match */
$route_match = $this->prophesize(RouteMatchInterface::class);
$route_match->getRawParameters()->willReturn(new ParameterBag(['entity_type' => 'node', 'var_name' => 1]));
$route_match->getParameters()->willReturn(new ParameterBag(['entity_type' => 'node', 'var_name' => $node]));
$route_match = $route_match->reveal();
$access_check = new EntityAccessCheck();
$this->assertEquals(AccessResult::allowed(), $access_check->access($route, $route_match, $account));
}
}

View file

@ -8,6 +8,8 @@
namespace Drupal\Tests\Core\Entity;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Drupal\Core\DependencyInjection\Container;
use Drupal\Core\Entity\EntityCreateAccessCheck;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
@ -32,6 +34,11 @@ class EntityCreateAccessCheckTest extends UnitTestCase {
*/
protected function setUp() {
parent::setUp();
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class)->reveal();
$container = new Container();
$container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($container);
}
/**
@ -40,9 +47,8 @@ class EntityCreateAccessCheckTest extends UnitTestCase {
* @return array
*/
public function providerTestAccess() {
$no_access = AccessResult::neutral()->cachePerPermissions();
$access = AccessResult::allowed()->cachePerPermissions();
$no_access_due_to_errors = AccessResult::neutral();
$no_access = FALSE;
$access = TRUE;
return array(
array('', 'entity_test', $no_access, $no_access),
@ -51,10 +57,10 @@ class EntityCreateAccessCheckTest extends UnitTestCase {
array('test_entity', 'entity_test:test_entity', $no_access, $no_access),
array('test_entity', 'entity_test:{bundle_argument}', $access, $access),
array('test_entity', 'entity_test:{bundle_argument}', $no_access, $no_access),
array('', 'entity_test:{bundle_argument}', $no_access, $no_access_due_to_errors),
array('', 'entity_test:{bundle_argument}', $no_access, $no_access, FALSE),
// When the bundle is not provided, access should be denied even if the
// access control handler would allow access.
array('', 'entity_test:{bundle_argument}', $access, $no_access_due_to_errors),
array('', 'entity_test:{bundle_argument}', $access, $no_access, FALSE),
);
}
@ -63,7 +69,15 @@ class EntityCreateAccessCheckTest extends UnitTestCase {
*
* @dataProvider providerTestAccess
*/
public function testAccess($entity_bundle, $requirement, $access, $expected) {
public function testAccess($entity_bundle, $requirement, $access, $expected, $expect_permission_context = TRUE) {
// Set up the access result objects for allowing or denying access.
$access_result = $access ? AccessResult::allowed()->cachePerPermissions() : AccessResult::neutral()->cachePerPermissions();
$expected_access_result = $expected ? AccessResult::allowed() : AccessResult::neutral();
if ($expect_permission_context) {
$expected_access_result->cachePerPermissions();
}
$entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
// Don't expect a call to the access control handler when we have a bundle
@ -73,7 +87,7 @@ class EntityCreateAccessCheckTest extends UnitTestCase {
$access_control_handler->expects($this->once())
->method('createAccess')
->with($entity_bundle)
->will($this->returnValue($access));
->will($this->returnValue($access_result));
$entity_manager->expects($this->any())
->method('getAccessControlHandler')
@ -101,7 +115,7 @@ class EntityCreateAccessCheckTest extends UnitTestCase {
->will($this->returnValue($raw_variables));
$account = $this->getMock('Drupal\Core\Session\AccountInterface');
$this->assertEquals($expected, $applies_check->access($route, $route_match, $account));
$this->assertEquals($expected_access_result, $applies_check->access($route, $route_match, $account));
}
}

View file

@ -137,64 +137,6 @@ class EntityListBuilderTest extends UnitTestCase {
$this->assertArrayHasKey('title', $operations[$operation_name]);
}
/**
* Tests that buildRow() returns a string which has been run through
* SafeMarkup::checkPlain().
*
* @dataProvider providerTestBuildRow
*
* @param string $input
* The entity label being passed into buildRow.
* @param string $expected
* The expected output of the label from buildRow.
* @param string $message
* The message to provide as output for the test.
* @param bool $ignorewarnings
* Whether or not to ignore PHP 5.3+ invalid multibyte sequence warnings.
*
* @see \Drupal\Core\Entity\EntityListBuilder::buildRow()
*/
public function testBuildRow($input, $expected, $message, $ignorewarnings = FALSE) {
$this->role->expects($this->any())
->method('label')
->will($this->returnValue($input));
if ($ignorewarnings) {
$built_row = @$this->entityListBuilder->buildRow($this->role);
}
else {
$built_row = $this->entityListBuilder->buildRow($this->role);
}
$this->assertEquals($built_row['label'], $expected, $message);
}
/**
* Data provider for testBuildRow().
*
* @see self::testBuildRow()
* @see \Drupal\Tests\Component\Utility\SafeMarkupTest::providerCheckPlain()
*
* @return array
* An array containing a string, the expected return from
* SafeMarkup::checkPlain, a message to be output for failures, and whether the
* test should be processed as multibyte.
*/
public function providerTestBuildRow() {
$tests = array();
// Checks that invalid multi-byte sequences are rejected.
$tests[] = array("Foo\xC0barbaz", '', 'EntityTestListBuilder::buildRow() rejects invalid sequence "Foo\xC0barbaz"', TRUE);
$tests[] = array("\xc2\"", '', 'EntityTestListBuilder::buildRow() rejects invalid sequence "\xc2\""', TRUE);
$tests[] = array("Fooÿñ", "Fooÿñ", 'EntityTestListBuilder::buildRow() accepts valid sequence "Fooÿñ"');
// Checks that special characters are escaped.
$tests[] = array("<script>", '&lt;script&gt;', 'EntityTestListBuilder::buildRow() escapes &lt;script&gt;');
$tests[] = array('<>&"\'', '&lt;&gt;&amp;&quot;&#039;', 'EntityTestListBuilder::buildRow() escapes reserved HTML characters.');
return $tests;
}
}
class TestEntityListBuilder extends EntityTestListBuilder {

File diff suppressed because it is too large Load diff

View file

@ -8,6 +8,7 @@
namespace Drupal\Tests\Core\Entity;
use Drupal\Core\Entity\EntityType;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Tests\UnitTestCase;
/**
@ -31,6 +32,29 @@ class EntityTypeTest extends UnitTestCase {
return new EntityType($definition);
}
/**
* @covers ::get
*
* @dataProvider providerTestGet
*/
public function testGet(array $defintion, $key, $expected) {
$entity_type = $this->setUpEntityType($defintion);
$this->assertSame($expected, $entity_type->get($key));
}
/**
* @covers ::set
* @covers ::get
*
* @dataProvider providerTestSet
*/
public function testSet($key, $value) {
$entity_type = $this->setUpEntityType([]);
$this->assertInstanceOf('Drupal\Core\Entity\EntityTypeInterface', $entity_type->set($key, $value));
$this->assertSame($value, $entity_type->get($key));
$this->assertNoPublicProperties($entity_type);
}
/**
* Tests the getKeys() method.
*
@ -64,6 +88,34 @@ class EntityTypeTest extends UnitTestCase {
$this->assertSame(FALSE, $entity_type->hasKey('bananas'));
}
/**
* Provides test data for testGet.
*/
public function providerTestGet() {
return [
[[], 'provider', NULL],
[['provider' => ''], 'provider', ''],
[['provider' => 'test'], 'provider', 'test'],
[[], 'something_additional', NULL],
[['something_additional' => ''], 'something_additional', ''],
[['something_additional' => 'additional'], 'something_additional', 'additional'],
];
}
/**
* Provides test data for testSet.
*/
public function providerTestSet() {
return [
['provider', NULL],
['provider', ''],
['provider', 'test'],
['something_additional', NULL],
['something_additional', ''],
['something_additional', 'additional'],
];
}
/**
* Provides test data.
*/
@ -272,4 +324,14 @@ class EntityTypeTest extends UnitTestCase {
$this->assertEquals([], $entity_type->getConstraints());
}
/**
* Asserts there on no public properties on the object instance.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
*/
protected function assertNoPublicProperties(EntityTypeInterface $entity_type) {
$reflection = new \ReflectionObject($entity_type);
$this->assertEmpty($reflection->getProperties(\ReflectionProperty::IS_PUBLIC));
}
}

View file

@ -18,6 +18,13 @@ use Drupal\Tests\UnitTestCase;
*/
class SqlContentEntityStorageSchemaTest extends UnitTestCase {
/**
* The mocked DB schema handler.
*
* @var \Drupal\Core\Database\Schema|\PHPUnit_Framework_MockObject_MockObject
*/
protected $dbSchemaHandler;
/**
* The mocked entity manager used in this test.
*
@ -1298,7 +1305,7 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
->with($this->entityType->id())
->will($this->returnValue($this->storageDefinitions));
$db_schema_handler = $this->getMockBuilder('Drupal\Core\Database\Schema')
$this->dbSchemaHandler = $this->getMockBuilder('Drupal\Core\Database\Schema')
->disableOriginalConstructor()
->getMock();
@ -1307,7 +1314,7 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
$expected_table_names = array_keys($expected);
$expected_table_schemas = array_values($expected);
$db_schema_handler->expects($this->any())
$this->dbSchemaHandler->expects($this->any())
->method('createTable')
->with(
$this->callback(function($table_name) use (&$invocation_count, $expected_table_names) {
@ -1327,17 +1334,21 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
->getMock();
$connection->expects($this->any())
->method('schema')
->will($this->returnValue($db_schema_handler));
->will($this->returnValue($this->dbSchemaHandler));
$key_value = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreInterface');
$this->storageSchema = $this->getMockBuilder('Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema')
->setConstructorArgs(array($this->entityManager, $this->entityType, $this->storage, $connection))
->setMethods(array('installedStorageSchema', 'loadEntitySchemaData', 'hasSharedTableNameChanges'))
->setMethods(array('installedStorageSchema', 'loadEntitySchemaData', 'hasSharedTableNameChanges', 'isTableEmpty'))
->getMock();
$this->storageSchema
->expects($this->any())
->method('installedStorageSchema')
->will($this->returnValue($key_value));
$this->storageSchema
->expects($this->any())
->method('isTableEmpty')
->willReturn(FALSE);
}
/**
@ -1380,4 +1391,95 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
}
}
/**
* ::onEntityTypeUpdate
*/
public function testonEntityTypeUpdateWithNewIndex() {
$this->entityType = $original_entity_type = new ContentEntityType(array(
'id' => 'entity_test',
'entity_keys' => array('id' => 'id'),
));
// Add a field with a really long index.
$this->setUpStorageDefinition('long_index_name', array(
'columns' => array(
'long_index_name' => array(
'type' => 'int',
),
),
'indexes' => array(
'long_index_name_really_long_long_name' => array(array('long_index_name', 10)),
),
));
$expected = array(
'entity_test' => array(
'description' => 'The base table for entity_test entities.',
'fields' => array(
'id' => array(
'type' => 'serial',
'not null' => TRUE,
),
'long_index_name' => array(
'type' => 'int',
'not null' => FALSE,
),
),
'indexes' => array(
'entity_test__b588603cb9' => array(
array('long_index_name', 10),
),
),
),
);
$this->setUpStorageSchema($expected);
$table_mapping = new DefaultTableMapping($this->entityType, $this->storageDefinitions);
$table_mapping->setFieldNames('entity_test', array_keys($this->storageDefinitions));
$table_mapping->setExtraColumns('entity_test', array('default_langcode'));
$this->storage->expects($this->any())
->method('getTableMapping')
->will($this->returnValue($table_mapping));
$this->storageSchema->expects($this->any())
->method('loadEntitySchemaData')
->willReturn([
'entity_test' => [
'indexes' => [
// A changed index definition.
'entity_test__b588603cb9' => ['longer_index_name'],
// An index that has been removed.
'entity_test__removed_field' => ['removed_field'],
],
],
]);
// The original indexes should be dropped before the new one is added.
$this->dbSchemaHandler->expects($this->at(0))
->method('dropIndex')
->with('entity_test', 'entity_test__b588603cb9');
$this->dbSchemaHandler->expects($this->at(1))
->method('dropIndex')
->with('entity_test', 'entity_test__removed_field');
$this->dbSchemaHandler->expects($this->atLeastOnce())
->method('fieldExists')
->willReturn(TRUE);
$this->dbSchemaHandler->expects($this->atLeastOnce())
->method('addIndex')
->with('entity_test', 'entity_test__b588603cb9', [['long_index_name', 10]], $this->callback(function($actual_value) use ($expected) {
$this->assertEquals($expected['entity_test']['indexes'], $actual_value['indexes']);
$this->assertEquals($expected['entity_test']['fields'], $actual_value['fields']);
// If the parameters don't match, the assertions above will throw an
// exception.
return TRUE;
}));
$this->assertNull(
$this->storageSchema->onEntityTypeUpdate($this->entityType, $original_entity_type)
);
}
}

View file

@ -12,7 +12,6 @@ use Drupal\Core\Routing\RouteBuildEvent;
use Drupal\Tests\UnitTestCase;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
/**
* @coversDefaultClass \Drupal\Core\EventSubscriber\SpecialAttributesRouteSubscriber
@ -20,22 +19,6 @@ use Symfony\Component\Routing\RouteCollection;
*/
class SpecialAttributesRouteSubscriberTest extends UnitTestCase {
/**
* The tested route subscriber.
*
* @var \Drupal\Core\EventSubscriber\SpecialAttributesRouteSubscriber
*/
protected $specialAttributesRouteSubscriber;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->specialAttributesRouteSubscriber = new SpecialAttributesRouteSubscriber();
}
/**
* Provides a list of routes with invalid route variables.
*
@ -43,14 +26,21 @@ class SpecialAttributesRouteSubscriberTest extends UnitTestCase {
* An array of invalid routes.
*/
public function providerTestOnRouteBuildingInvalidVariables() {
$routes = array();
$routes[] = array(new Route('/test/{system_path}'));
$routes[] = array(new Route('/test/{_legacy}'));
$routes[] = array(new Route('/test/{' . RouteObjectInterface::ROUTE_OBJECT . '}'));
$routes[] = array(new Route('/test/{' . RouteObjectInterface::ROUTE_NAME . '}'));
$routes[] = array(new Route('/test/{_content}'));
$routes[] = array(new Route('/test/{_form}'));
$routes[] = array(new Route('/test/{_raw_variables}'));
// Build an array of mock route objects based on paths.
$routes = [];
$paths = [
'/test/{system_path}',
'/test/{_legacy}',
'/test/{' . RouteObjectInterface::ROUTE_OBJECT . '}',
'/test/{' . RouteObjectInterface::ROUTE_NAME . '}',
'/test/{_content}',
'/test/{_form}',
'/test/{_raw_variables}',
];
foreach ($paths as $path) {
$routes[] = [new Route($path)];
}
return $routes;
}
@ -62,11 +52,18 @@ class SpecialAttributesRouteSubscriberTest extends UnitTestCase {
* An array of valid routes.
*/
public function providerTestOnRouteBuildingValidVariables() {
$routes = array();
$routes[] = array(new Route('/test/{account}'));
$routes[] = array(new Route('/test/{node}'));
$routes[] = array(new Route('/test/{user}'));
$routes[] = array(new Route('/test/{entity_test}'));
// Build an array of mock route objects based on paths.
$routes = [];
$paths = [
'/test/{account}',
'/test/{node}',
'/test/{user}',
'/test/{entity_test}',
];
foreach ($paths as $path) {
$routes[] = [new Route($path)];
}
return $routes;
}
@ -78,12 +75,16 @@ class SpecialAttributesRouteSubscriberTest extends UnitTestCase {
* The route to check.
*
* @dataProvider providerTestOnRouteBuildingValidVariables
*
* @covers ::onAlterRoutes
*/
public function testOnRouteBuildingValidVariables(Route $route) {
$route_collection = new RouteCollection();
$route_collection = $this->getMock('Symfony\Component\Routing\RouteCollection', NULL);
$route_collection->add('test', $route);
$event = new RouteBuildEvent($route_collection, 'test');
$this->specialAttributesRouteSubscriber->onAlterRoutes($event);
$subscriber = new SpecialAttributesRouteSubscriber();
$this->assertNull($subscriber->onAlterRoutes($event));
}
/**
@ -95,12 +96,16 @@ class SpecialAttributesRouteSubscriberTest extends UnitTestCase {
* @dataProvider providerTestOnRouteBuildingInvalidVariables
* @expectedException \PHPUnit_Framework_Error_Warning
* @expectedExceptionMessage uses reserved variable names
*
* @covers ::onAlterRoutes
*/
public function testOnRouteBuildingInvalidVariables(Route $route) {
$route_collection = new RouteCollection();
$route_collection = $this->getMock('Symfony\Component\Routing\RouteCollection', NULL);
$route_collection->add('test', $route);
$event = new RouteBuildEvent($route_collection, 'test');
$this->specialAttributesRouteSubscriber->onAlterRoutes($event);
$subscriber = new SpecialAttributesRouteSubscriber();
$subscriber->onAlterRoutes($event);
}
}

View file

@ -0,0 +1,170 @@
<?php
/**
* @file
* Contains \Drupal\system\Tests\Extension\InfoParserUnitTest.
*/
namespace Drupal\Tests\Core\Extension;
use Drupal\Core\Extension\InfoParser;
use Drupal\Tests\UnitTestCase;
use org\bovigo\vfs\vfsStream;
/**
* Tests InfoParser class and exception.
*
* Files for this test are stored in core/modules/system/tests/fixtures and end
* with .info.txt instead of info.yml in order not not be considered as real
* extensions.
*
* @coversDefaultClass \Drupal\Core\Extension\InfoParser
*
* @group Extension
*/
class InfoParserUnitTest extends UnitTestCase {
/**
* The InfoParser object.
*
* @var \Drupal\Core\Extension\InfoParser
*/
protected $infoParser;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->infoParser = new InfoParser();
}
/**
* Tests the functionality of the infoParser object.
*
* @covers ::parse
*/
public function testInfoParserNonExisting() {
vfsStream::setup('modules');
$info = $this->infoParser->parse(vfsStream::url('modules') . '/does_not_exist.info.txt');
$this->assertTrue(empty($info), 'Non existing info.yml returns empty array.');
}
/**
* Test if correct exception is thrown for a broken info file.
*
* @covers ::parse
*
* @expectedException \Drupal\Core\Extension\InfoParserException
* @expectedExceptionMessageRegExp #broken\.info\.txt#
*/
public function testInfoParserBroken() {
$broken_info = <<<BROKEN_INFO
# info.yml for testing broken YAML parsing exception handling.
name: File
type: module
description: 'Defines a file field type.'
package: Core
version: VERSION
core: 8.x
dependencies::;;
- field
BROKEN_INFO;
vfsStream::setup('modules');
vfsStream::create([
'fixtures' => [
'broken.info.txt' => $broken_info,
],
]);
$filename = vfsStream::url('modules/fixtures/broken.info.txt');
$this->infoParser->parse($filename);
}
/**
* Tests that missing required keys are detected.
*
* @covers ::parse
*
* @expectedException \Drupal\Core\Extension\InfoParserException
* @expectedExceptionMessageRegExp #Missing required keys \(type, core, name\) in .+?missing_keys\.info\.txt#
*/
public function testInfoParserMissingKeys() {
$missing_keys = <<<MISSINGKEYS
# info.yml for testing missing name, description, and type keys.
package: Core
version: VERSION
dependencies:
- field
MISSINGKEYS;
vfsStream::setup('modules');
vfsStream::create([
'fixtures' => [
'missing_keys.info.txt' => $missing_keys,
],
]);
$filename = vfsStream::url('modules/fixtures/missing_keys.info.txt');
$this->infoParser->parse($filename);
}
/**
* Tests that missing required key is detected.
*
* @covers ::parse
*
* @expectedException \Drupal\Core\Extension\InfoParserException
* @expectedExceptionMessageRegExp #Missing required keys \(type\) in .+?missing_key\.info\.txt#
*/
public function testInfoParserMissingKey() {
$missing_key = <<<MISSINGKEY
# info.yml for testing missing type key.
name: File
description: 'Defines a file field type.'
package: Core
version: VERSION
core: 8.x
dependencies:
- field
MISSINGKEY;
vfsStream::setup('modules');
vfsStream::create([
'fixtures' => [
'missing_key.info.txt' => $missing_key,
],
]);
$filename = vfsStream::url('modules/fixtures/missing_key.info.txt');
$this->infoParser->parse($filename);
}
/**
* Tests common info file.
*
* @covers ::parse
*/
public function testInfoParserCommonInfo() {
$common = <<<COMMONTEST
core: 8.x
name: common_test
type: module
description: 'testing info file parsing'
simple_string: 'A simple string'
version: "VERSION"
double_colon: dummyClassName::
COMMONTEST;
vfsStream::setup('modules');
vfsStream::create([
'fixtures' => [
'common_test.info.txt' => $common,
],
]);
$info_values = $this->infoParser->parse(vfsStream::url('modules/fixtures/common_test.info.txt'));
$this->assertEquals($info_values['simple_string'], 'A simple string', 'Simple string value was parsed correctly.');
$this->assertEquals($info_values['version'], \Drupal::VERSION, 'Constant value was parsed correctly.');
$this->assertEquals($info_values['double_colon'], 'dummyClassName::', 'Value containing double-colon was parsed correctly.');
}
}

View file

@ -7,7 +7,6 @@
namespace Drupal\Tests\Core\Extension;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Tests\UnitTestCase;
/**
@ -72,7 +71,7 @@ class RequiredModuleUninstallValidatorTest extends UnitTestCase {
->method('getModuleInfoByModule')
->willReturn(['required' => TRUE, 'name' => $module]);
$expected = [SafeMarkup::format('The @module module is required', ['@module' => $module])];
$expected = ["The $module module is required"];
$reasons = $this->uninstallValidator->validate($module);
$this->assertSame($expected, $reasons);
}

View file

@ -0,0 +1,63 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Field\FieldFilteredStringTest.
*/
namespace Drupal\Tests\Core\Field;
use Drupal\Tests\UnitTestCase;
use Drupal\Core\Field\FieldFilteredString;
use Drupal\Component\Utility\SafeStringInterface;
/**
* @coversDefaultClass \Drupal\Core\Field\FieldFilteredString
* @group Field
*/
class FieldFilteredStringTest extends UnitTestCase {
/**
* @covers ::create
* @dataProvider providerTestCreate
*/
public function testCreate($string, $expected, $instance_of_check) {
$filtered_string = FieldFilteredString::create($string);
if ($instance_of_check) {
$this->assertInstanceOf(FieldFilteredString::class, $filtered_string);
}
$this->assertSame($expected, (string) $filtered_string);
}
/**
* Provides data for testCreate().
*/
public function providerTestCreate() {
$data = [];
$data[] = ['', '', FALSE];
// Certain tags are filtered.
$data[] = ['<script>teststring</script>', 'teststring', TRUE];
// Certain tags are not filtered.
$data[] = ['<em>teststring</em>', '<em>teststring</em>', TRUE];
// HTML will be normalized.
$data[] = ['<em>teststring', '<em>teststring</em>', TRUE];
// Even safe strings will be escaped.
$safe_string = $this->prophesize(SafeStringInterface::class);
$safe_string->__toString()->willReturn('<script>teststring</script>');
$data[] = [$safe_string->reveal(), 'teststring', TRUE];
return $data;
}
/**
* @covers: ::displayAllowedTags
*/
public function testdisplayAllowedTags() {
$expected = '<a> <b> <big> <code> <del> <em> <i> <ins> <pre> <q> <small> <span> <strong> <sub> <sup> <tt> <ol> <ul> <li> <p> <br> <img>';
$this->assertSame($expected, FieldFilteredString::displayAllowedTags());
}
}

View file

@ -12,13 +12,18 @@ use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\AccessResultForbidden;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Form\EnforcedResponseException;
use Drupal\Core\Form\FormBuilder;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormInterface;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* @coversDefaultClass \Drupal\Core\Form\FormBuilder
@ -26,6 +31,25 @@ use Symfony\Component\HttpFoundation\RequestStack;
*/
class FormBuilderTest extends FormTestBase {
/**
* The dependency injection container.
*
* @var \Symfony\Component\DependencyInjection\ContainerBuilder
*/
protected $container;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->container = new ContainerBuilder();
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class)->reveal();
$this->container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($this->container);
}
/**
* Tests the getFormId() method with a string based form ID.
*
@ -571,7 +595,7 @@ class FormBuilderTest extends FormTestBase {
$data['access-false-root'] = [$clone, $expected_access];
$clone = $element;
$access_result = AccessResult::forbidden()->addCacheContexts(['user']);
$access_result = AccessResult::forbidden();
$clone['#access'] = $access_result;
$expected_access = [];
@ -603,11 +627,9 @@ class FormBuilderTest extends FormTestBase {
// Allow access on the most outer level but forbid otherwise.
$clone = $element;
$access_result_allowed = AccessResult::allowed()
->addCacheContexts(['user']);
$access_result_allowed = AccessResult::allowed();
$clone['#access'] = $access_result_allowed;
$access_result_forbidden = AccessResult::forbidden()
->addCacheContexts(['user']);
$access_result_forbidden = AccessResult::forbidden();
$clone['child0']['#access'] = $access_result_forbidden;
$expected_access = [];
@ -662,6 +684,149 @@ class FormBuilderTest extends FormTestBase {
return $data;
}
/**
* @covers ::valueCallableIsSafe
*
* @dataProvider providerTestValueCallableIsSafe
*/
public function testValueCallableIsSafe($callback, $expected) {
$method = new \ReflectionMethod(FormBuilder::class, 'valueCallableIsSafe');
$method->setAccessible(true);
$is_safe = $method->invoke($this->formBuilder, $callback);
$this->assertSame($expected, $is_safe);
}
public function providerTestValueCallableIsSafe() {
$data = [];
$data['string_no_slash'] = [
'Drupal\Core\Render\Element\Token::valueCallback',
TRUE,
];
$data['string_with_slash'] = [
'\Drupal\Core\Render\Element\Token::valueCallback',
TRUE,
];
$data['array_no_slash'] = [
['Drupal\Core\Render\Element\Token', 'valueCallback'],
TRUE,
];
$data['array_with_slash'] = [
['\Drupal\Core\Render\Element\Token', 'valueCallback'],
TRUE,
];
$data['closure'] = [
function () {},
FALSE,
];
return $data;
}
/**
* @covers ::doBuildForm
*
* @dataProvider providerTestInvalidToken
*/
public function testInvalidToken($expected, $valid_token, $user_is_authenticated) {
$form_token = 'the_form_token';
$form_id = 'test_form_id';
if (is_bool($valid_token)) {
$this->csrfToken->expects($this->any())
->method('get')
->willReturnArgument(0);
$this->csrfToken->expects($this->atLeastOnce())
->method('validate')
->will($this->returnValueMap([
[$form_token, $form_id, $valid_token],
[$form_id, $form_id, $valid_token],
]));
}
$current_user = $this->prophesize(AccountInterface::class);
$current_user->isAuthenticated()->willReturn($user_is_authenticated);
$property = new \ReflectionProperty(FormBuilder::class, 'currentUser');
$property->setAccessible(TRUE);
$property->setValue($this->formBuilder, $current_user->reveal());
$expected_form = $form_id();
$form_arg = $this->getMockForm($form_id, $expected_form);
$form_state = new FormState();
$input['form_id'] = $form_id;
$input['form_token'] = $form_token;
$form_state->setUserInput($input);
$this->simulateFormSubmission($form_id, $form_arg, $form_state, FALSE);
$this->assertSame($expected, $form_state->hasInvalidToken());
}
public function providerTestInvalidToken() {
$data = [];
$data['authenticated_invalid'] = [TRUE, FALSE, TRUE];
$data['authenticated_valid'] = [FALSE, TRUE, TRUE];
// If the user is not authenticated, we will not have a token.
$data['anonymous'] = [FALSE, NULL, FALSE];
return $data;
}
/**
* @covers ::prepareForm
*
* @dataProvider providerTestFormTokenCacheability
*/
function testFormTokenCacheability($token, $is_authenticated, $expected_form_cacheability, $expected_token_cacheability) {
$user = $this->prophesize(AccountProxyInterface::class);
$user->isAuthenticated()
->willReturn($is_authenticated);
$this->container->set('current_user', $user->reveal());
\Drupal::setContainer($this->container);
$form_id = 'test_form_id';
$form = $form_id();
if (isset($token)) {
$form['#token'] = $token;
}
$form_arg = $this->getMock('Drupal\Core\Form\FormInterface');
$form_arg->expects($this->once())
->method('getFormId')
->will($this->returnValue($form_id));
$form_arg->expects($this->once())
->method('buildForm')
->will($this->returnValue($form));
$form_state = new FormState();
$built_form = $this->formBuilder->buildForm($form_arg, $form_state);
if (!isset($expected_form_cacheability)) {
$this->assertFalse(isset($built_form['#cache']));
}
else {
$this->assertTrue(isset($built_form['#cache']));
$this->assertEquals($expected_form_cacheability, $built_form['#cache']);
}
if (!isset($expected_token_cacheability)) {
$this->assertFalse(isset($built_form['form_token']));
}
else {
$this->assertTrue(isset($built_form['form_token']));
$this->assertEquals($expected_token_cacheability, $built_form['form_token']['#cache']);
}
}
/**
* Data provider for testFormTokenCacheability.
*
* @return array
*/
function providerTestFormTokenCacheability() {
return [
'token:none,authenticated:true' => [NULL, TRUE, ['contexts' => ['user.roles:authenticated']], ['max-age' => 0]],
'token:false,authenticated:true' => [FALSE, TRUE, NULL, NULL],
'token:none,authenticated:false' => [NULL, FALSE, ['contexts' => ['user.roles:authenticated']], NULL],
'token:false,authenticated:false' => [FALSE, FALSE, NULL, NULL],
];
}
}
class TestForm implements FormInterface {

View file

@ -427,9 +427,9 @@ class FormCacheTest extends UnitTestCase {
* @covers ::setCache
*/
public function testSetCacheWithSafeStrings() {
// A call to SafeMarkup::set() is appropriate in this test as a way to add a
// string to the safe list in the simplest way possible. Normally, avoid it.
SafeMarkup::set('a_safe_string');
// A call to SafeMarkup::format() is appropriate in this test as a way to
// add a string to the safe list in the simplest way possible.
SafeMarkup::format('@value', ['@value' => 'a_safe_string']);
$form_build_id = 'the_form_build_id';
$form = [
'#form_id' => 'the_form_id'

View file

@ -25,8 +25,9 @@ class FormErrorHandlerTest extends UnitTestCase {
$link_generator->expects($this->any())
->method('generate')
->willReturnArgument(0);
$renderer = $this->getMock('\Drupal\Core\Render\RendererInterface');
$form_error_handler = $this->getMockBuilder('Drupal\Core\Form\FormErrorHandler')
->setConstructorArgs([$this->getStringTranslationStub(), $link_generator])
->setConstructorArgs([$this->getStringTranslationStub(), $link_generator, $renderer])
->setMethods(['drupalSetMessage'])
->getMock();
@ -41,7 +42,13 @@ class FormErrorHandlerTest extends UnitTestCase {
->with('this missing element is invalid', 'error');
$form_error_handler->expects($this->at(3))
->method('drupalSetMessage')
->with('3 errors have been found: Test 1, Test 2 &amp; a half, Test 3', 'error');
->with('3 errors have been found: <ul-comma-list-mock><li-mock>Test 1</li-mock><li-mock>Test 2 &amp; a half</li-mock><li-mock>Test 3</li-mock></ul-comma-list-mock>', 'error');
$renderer->expects($this->any())
->method('renderPlain')
->will($this->returnCallback(function ($render_array) {
return $render_array[0]['#markup'] . '<ul-comma-list-mock><li-mock>' . implode(array_map('htmlspecialchars', $render_array[1]['#items']), '</li-mock><li-mock>') . '</li-mock></ul-comma-list-mock>';
}));
$form = [
'#parents' => [],
@ -103,7 +110,7 @@ class FormErrorHandlerTest extends UnitTestCase {
*/
public function testSetElementErrorsFromFormState() {
$form_error_handler = $this->getMockBuilder('Drupal\Core\Form\FormErrorHandler')
->setConstructorArgs([$this->getStringTranslationStub(), $this->getMock('Drupal\Core\Utility\LinkGeneratorInterface')])
->setConstructorArgs([$this->getStringTranslationStub(), $this->getMock('Drupal\Core\Utility\LinkGeneratorInterface'), $this->getMock('\Drupal\Core\Render\RendererInterface')])
->setMethods(['drupalSetMessage'])
->getMock();

View file

@ -209,8 +209,7 @@ abstract class FormTestBase extends UnitTestCase {
* Provides a mocked form object.
*
* @param string $form_id
* (optional) The form ID to be used. If none is provided, the form will be
* set with no expectation about getFormId().
* The form ID to be used.
* @param mixed $expected_form
* (optional) If provided, the expected form response for buildForm() to
* return. Defaults to NULL.

View file

@ -7,7 +7,6 @@
namespace Drupal\Tests\Core\Form;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Form\FormState;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\Request;
@ -468,7 +467,7 @@ class FormValidatorTest extends UnitTestCase {
'#maxlength' => 7,
'#value' => $this->randomMachineName(8),
),
SafeMarkup::format('!name cannot be longer than %max characters but is currently %length characters long.', array('!name' => 'Test', '%max' => '7', '%length' => 8)),
'Test cannot be longer than <em class="placeholder">7</em> characters but is currently <em class="placeholder">8</em> characters long.',
FALSE,
),
);

View file

@ -8,6 +8,8 @@
namespace Drupal\Tests\Core\Menu;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Drupal\Core\DependencyInjection\Container;
use Drupal\Core\Menu\DefaultMenuLinkTreeManipulators;
use Drupal\Core\Menu\MenuLinkTreeElement;
use Drupal\Tests\UnitTestCase;
@ -76,6 +78,11 @@ class DefaultMenuLinkTreeManipulatorsTest extends UnitTestCase {
->getMock();
$this->defaultMenuTreeManipulators = new DefaultMenuLinkTreeManipulators($this->accessManager, $this->currentUser, $this->queryFactory);
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class)->reveal();
$container = new Container();
$container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($container);
}
/**

View file

@ -10,6 +10,8 @@ namespace Drupal\Tests\Core\Menu;
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Component\Plugin\Factory\FactoryInterface;
use Drupal\Core\Access\AccessManagerInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\AccessResultForbidden;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\Language;
@ -109,10 +111,11 @@ class LocalActionManagerTest extends UnitTestCase {
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
$access_result = new AccessResultForbidden();
$this->accessManager = $this->getMock('Drupal\Core\Access\AccessManagerInterface');
$this->accessManager->expects($this->any())
->method('checkNamedRoute')
->will($this->returnValue(FALSE));
->willReturn($access_result);
$this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
$this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
$this->factory = $this->getMock('Drupal\Component\Plugin\Factory\FactoryInterface');
@ -202,7 +205,7 @@ class LocalActionManagerTest extends UnitTestCase {
'url' => Url::fromRoute('test_route_2'),
'localized_options' => '',
),
'#access' => FALSE,
'#access' => AccessResult::forbidden(),
'#weight' => 0,
),
),
@ -236,7 +239,7 @@ class LocalActionManagerTest extends UnitTestCase {
'url' => Url::fromRoute('test_route_2'),
'localized_options' => '',
),
'#access' => FALSE,
'#access' => AccessResult::forbidden(),
'#weight' => 0,
),
),
@ -271,7 +274,7 @@ class LocalActionManagerTest extends UnitTestCase {
'url' => Url::fromRoute('test_route_2'),
'localized_options' => '',
),
'#access' => FALSE,
'#access' => AccessResult::forbidden(),
'#weight' => 1,
),
'plugin_id_2' => array(
@ -281,7 +284,7 @@ class LocalActionManagerTest extends UnitTestCase {
'url' => Url::fromRoute('test_route_3'),
'localized_options' => '',
),
'#access' => FALSE,
'#access' => AccessResult::forbidden(),
'#weight' => 0,
),
),
@ -318,7 +321,7 @@ class LocalActionManagerTest extends UnitTestCase {
'url' => Url::fromRoute('test_route_2', ['test1']),
'localized_options' => '',
),
'#access' => FALSE,
'#access' => AccessResult::forbidden(),
'#weight' => 1,
),
'plugin_id_2' => array(
@ -328,7 +331,7 @@ class LocalActionManagerTest extends UnitTestCase {
'url' => Url::fromRoute('test_route_2', ['test2']),
'localized_options' => '',
),
'#access' => FALSE,
'#access' => AccessResult::forbidden(),
'#weight' => 0,
),
),

View file

@ -0,0 +1,68 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Menu\MenuLinkDefaultTest.
*/
namespace Drupal\Tests\Core\Menu;
use Drupal\Core\Menu\MenuLinkDefault;
use Drupal\Core\Menu\StaticMenuLinkOverridesInterface;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Menu\MenuLinkDefault
* @group Menu
*/
class MenuLinkDefaultTest extends UnitTestCase {
/**
* @covers ::updateLink
*/
public function testUpdateLink() {
$plugin_definition = [
'title' => 'Hey jude',
'enabled' => 1,
'expanded' => 1,
'menu_name' => 'admin',
'parent' => '',
'weight' => 10,
];
$expected_plugin_definition = $plugin_definition;
$expected_plugin_definition['weight'] = -10;
$static_override = $this->prophesize(StaticMenuLinkOverridesInterface::class);
$static_override->saveOverride('example_menu_link', $expected_plugin_definition);
$static_override = $static_override->reveal();
$menu_link = new MenuLinkDefault([], 'example_menu_link', $plugin_definition, $static_override);
$this->assertEquals($expected_plugin_definition, $menu_link->updateLink(['weight' => -10], TRUE));
}
/**
* @covers ::updateLink
*/
public function testUpdateLinkWithoutPersist() {
$plugin_definition = [
'title' => 'Hey jude',
'enabled' => 1,
'expanded' => 1,
'menu_name' => 'admin',
'parent' => '',
'weight' => 10,
];
$expected_plugin_definition = $plugin_definition;
$expected_plugin_definition['weight'] = -10;
$static_override = $this->prophesize(StaticMenuLinkOverridesInterface::class);
$static_override->saveOverride()->shouldNotBeCalled();
$static_override = $static_override->reveal();
$menu_link = new MenuLinkDefault([], 'example_menu_link', $plugin_definition, $static_override);
$this->assertEquals($expected_plugin_definition, $menu_link->updateLink(['weight' => -10], FALSE));
}
}

View file

@ -7,7 +7,6 @@
namespace Drupal\Tests\Core\Path;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Path\PathMatcher;
use Drupal\Tests\UnitTestCase;
@ -49,12 +48,7 @@ class PathMatcherTest extends UnitTestCase {
public function testMatchPath($patterns, $paths) {
foreach ($paths as $path => $expected_result) {
$actual_result = $this->pathMatcher->matchPath($path, $patterns);
$this->assertEquals($actual_result, $expected_result, SafeMarkup::format('Tried matching the path <code>@path</code> to the pattern <pre>@patterns</pre> - expected @expected, got @actual.', array(
'@path' => $path,
'@patterns' => $patterns,
'@expected' => var_export($expected_result, TRUE),
'@actual' => var_export($actual_result, TRUE),
)));
$this->assertEquals($actual_result, $expected_result, "Tried matching the path '$path' to the pattern '$patterns'.");
}
}

View file

@ -7,6 +7,7 @@
namespace Drupal\Tests\Core\Render\Element;
use Drupal\Core\Render\SafeString;
use Drupal\Tests\UnitTestCase;
use Drupal\Core\Render\Element\HtmlTag;
@ -34,7 +35,7 @@ class HtmlTagTest extends UnitTestCase {
public function testPreRenderHtmlTag($element, $expected) {
$result = HtmlTag::preRenderHtmlTag($element);
$this->assertArrayHasKey('#markup', $result);
$this->assertSame($expected, $result['#markup']);
$this->assertEquals($expected, $result['#markup']);
}
/**
@ -45,12 +46,10 @@ class HtmlTagTest extends UnitTestCase {
// Value prefix/suffix.
$element = array(
'#value_prefix' => 'value_prefix|',
'#value_suffix' => '|value_suffix',
'#value' => 'value',
'#tag' => 'p',
);
$tags[] = array($element, '<p>value_prefix|value|value_suffix</p>' . "\n");
$tags[] = array($element, '<p>value</p>' . "\n");
// Normal element without a value should not result in a void element.
$element = array(
@ -77,6 +76,27 @@ class HtmlTagTest extends UnitTestCase {
$element['#noscript'] = TRUE;
$tags[] = array($element, '<noscript><div class="test" id="id">value</div>' . "\n" . '</noscript>');
// Ensure that #tag is sanitised.
$element = array(
'#tag' => 'p><script>alert()</script><p',
'#value' => 'value',
);
$tags[] = array($element, "<p&gt;&lt;script&gt;alert()&lt;/script&gt;&lt;p>value</p&gt;&lt;script&gt;alert()&lt;/script&gt;&lt;p>\n");
// Ensure that #value is not filtered if it is marked as safe.
$element = array(
'#tag' => 'p',
'#value' => SafeString::create('<script>value</script>'),
);
$tags[] = array($element, "<p><script>value</script></p>\n");
// Ensure that #value is filtered if it is not safe.
$element = array(
'#tag' => 'p',
'#value' => '<script>value</script>',
);
$tags[] = array($element, "<p>value</p>\n");
return $tags;
}
@ -84,8 +104,12 @@ class HtmlTagTest extends UnitTestCase {
* @covers ::preRenderConditionalComments
* @dataProvider providerPreRenderConditionalComments
*/
public function testPreRenderConditionalComments($element, $expected) {
$this->assertSame($expected, HtmlTag::preRenderConditionalComments($element));
public function testPreRenderConditionalComments($element, $expected, $set_safe = FALSE) {
if ($set_safe) {
$element['#prefix'] = SafeString::create($element['#prefix']);
$element['#suffix'] = SafeString::create($element['#suffix']);
}
$this->assertEquals($expected, HtmlTag::preRenderConditionalComments($element));
}
/**
@ -142,6 +166,26 @@ class HtmlTagTest extends UnitTestCase {
$expected['#suffix'] = "<!--<![endif]-->\n";
$tags[] = array($element, $expected);
// Prefix and suffix filtering if not safe.
$element = array(
'#tag' => 'link',
'#browsers' => array(
'IE' => FALSE,
),
'#prefix' => '<blink>prefix</blink>',
'#suffix' => '<blink>suffix</blink>',
);
$expected = $element;
$expected['#prefix'] = "\n<!--[if !IE]><!-->\nprefix";
$expected['#suffix'] = "suffix<!--<![endif]-->\n";
$tags[] = array($element, $expected);
// Prefix and suffix filtering if marked as safe. This has to come after the
// previous test case.
$expected['#prefix'] = "\n<!--[if !IE]><!-->\n<blink>prefix</blink>";
$expected['#suffix'] = "<blink>suffix</blink><!--<![endif]-->\n";
$tags[] = array($element, $expected, TRUE);
return $tags;
}

View file

@ -0,0 +1,45 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Render\Element\MachineNameTest.
*/
namespace Drupal\Tests\Core\Render\Element;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\MachineName;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Render\Element\MachineName
* @group Render
*/
class MachineNameTest extends UnitTestCase {
/**
* @covers ::valueCallback
*
* @dataProvider providerTestValueCallback
*/
public function testValueCallback($expected, $input) {
$element = [];
$form_state = $this->prophesize(FormStateInterface::class)->reveal();
$this->assertSame($expected, MachineName::valueCallback($element, $input, $form_state));
}
/**
* Data provider for testValueCallback().
*/
public function providerTestValueCallback() {
$data = [];
$data[] = [NULL, FALSE];
$data[] = [NULL, NULL];
$data[] = ['', ['test']];
$data[] = ['test', 'test'];
$data[] = ['123', 123];
return $data;
}
}

View file

@ -0,0 +1,45 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Render\Element\PasswordConfirmTest.
*/
namespace Drupal\Tests\Core\Render\Element;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\PasswordConfirm;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Render\Element\PasswordConfirm
* @group Render
*/
class PasswordConfirmTest extends UnitTestCase {
/**
* @covers ::valueCallback
*
* @dataProvider providerTestValueCallback
*/
public function testValueCallback($expected, $element, $input) {
$form_state = $this->prophesize(FormStateInterface::class)->reveal();
$this->assertSame($expected, PasswordConfirm::valueCallback($element, $input, $form_state));
}
/**
* Data provider for testValueCallback().
*/
public function providerTestValueCallback() {
$data = [];
$data[] = [['pass1' => '', 'pass2' => ''], [], NULL];
$data[] = [['pass1' => '', 'pass2' => ''], ['#default_value' => ['pass2' => 'value']], NULL];
$data[] = [['pass2' => 'value', 'pass1' => ''], ['#default_value' => ['pass2' => 'value']], FALSE];
$data[] = [['pass1' => '123456', 'pass2' => 'qwerty'], [], ['pass1' => '123456', 'pass2' => 'qwerty']];
$data[] = [['pass1' => '123', 'pass2' => '234'], [], ['pass1' => 123, 'pass2' => 234]];
$data[] = [['pass1' => '', 'pass2' => '234'], [], ['pass1' => ['array'], 'pass2' => 234]];
return $data;
}
}

View file

@ -0,0 +1,45 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Render\Element\PasswordTest.
*/
namespace Drupal\Tests\Core\Render\Element;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\Password;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Render\Element\Password
* @group Render
*/
class PasswordTest extends UnitTestCase {
/**
* @covers ::valueCallback
*
* @dataProvider providerTestValueCallback
*/
public function testValueCallback($expected, $input) {
$element = [];
$form_state = $this->prophesize(FormStateInterface::class)->reveal();
$this->assertSame($expected, Password::valueCallback($element, $input, $form_state));
}
/**
* Data provider for testValueCallback().
*/
public function providerTestValueCallback() {
$data = [];
$data[] = [NULL, FALSE];
$data[] = [NULL, NULL];
$data[] = ['', ['test']];
$data[] = ['test', 'test'];
$data[] = ['123', 123];
return $data;
}
}

View file

@ -0,0 +1,45 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Render\Element\TextareaTest.
*/
namespace Drupal\Tests\Core\Render\Element;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\Textarea;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Render\Element\Textarea
* @group Render
*/
class TextareaTest extends UnitTestCase {
/**
* @covers ::valueCallback
*
* @dataProvider providerTestValueCallback
*/
public function testValueCallback($expected, $input) {
$element = [];
$form_state = $this->prophesize(FormStateInterface::class)->reveal();
$this->assertSame($expected, Textarea::valueCallback($element, $input, $form_state));
}
/**
* Data provider for testValueCallback().
*/
public function providerTestValueCallback() {
$data = [];
$data[] = [NULL, FALSE];
$data[] = [NULL, NULL];
$data[] = ['', ['test']];
$data[] = ['test', 'test'];
$data[] = ['123', 123];
return $data;
}
}

View file

@ -0,0 +1,46 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Render\Element\TextfieldTest.
*/
namespace Drupal\Tests\Core\Render\Element;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\Textfield;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Render\Element\Textfield
* @group Render
*/
class TextfieldTest extends UnitTestCase {
/**
* @covers ::valueCallback
*
* @dataProvider providerTestValueCallback
*/
public function testValueCallback($expected, $input) {
$element = [];
$form_state = $this->prophesize(FormStateInterface::class)->reveal();
$this->assertSame($expected, Textfield::valueCallback($element, $input, $form_state));
}
/**
* Data provider for testValueCallback().
*/
public function providerTestValueCallback() {
$data = [];
$data[] = [NULL, FALSE];
$data[] = [NULL, NULL];
$data[] = ['', ['test']];
$data[] = ['test', 'test'];
$data[] = ['123', 123];
$data[] = ['testwithnewline', "test\nwith\rnewline"];
return $data;
}
}

View file

@ -0,0 +1,45 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Render\Element\TokenTest.
*/
namespace Drupal\Tests\Core\Render\Element;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\Token;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Render\Element\Token
* @group Render
*/
class TokenTest extends UnitTestCase {
/**
* @covers ::valueCallback
*
* @dataProvider providerTestValueCallback
*/
public function testValueCallback($expected, $input) {
$element = [];
$form_state = $this->prophesize(FormStateInterface::class)->reveal();
$this->assertSame($expected, Token::valueCallback($element, $input, $form_state));
}
/**
* Data provider for testValueCallback().
*/
public function providerTestValueCallback() {
$data = [];
$data[] = [NULL, FALSE];
$data[] = [NULL, NULL];
$data[] = ['', ['test']];
$data[] = ['test', 'test'];
$data[] = ['123', 123];
return $data;
}
}

View file

@ -66,101 +66,6 @@ class ElementInfoManagerTest extends UnitTestCase {
$this->elementInfo = new ElementInfoManager(new \ArrayObject(), $this->cache, $this->cacheTagsInvalidator, $this->moduleHandler, $this->themeManager);
}
/**
* Tests the getInfo method.
*
* @covers ::getInfo
* @covers ::buildInfo
*
* @dataProvider providerTestGetInfo
*/
public function testGetInfo($type, $expected_info, $element_info, callable $alter_callback = NULL) {
$this->moduleHandler->expects($this->once())
->method('invokeAll')
->with('element_info')
->will($this->returnValue($element_info));
$this->moduleHandler->expects($this->once())
->method('alter')
->with('element_info', $this->anything())
->will($this->returnCallback($alter_callback ?: function($info) {
return $info;
}));
$this->themeManager->expects($this->once())
->method('getActiveTheme')
->willReturn(new ActiveTheme(['name' => 'test']));
$this->themeManager->expects($this->once())
->method('alter')
->with('element_info', $this->anything())
->will($this->returnCallback($alter_callback ?: function($info) {
return $info;
}));
$this->cache->expects($this->at(0))
->method('get')
->with('element_info_build:test')
->will($this->returnValue(FALSE));
$this->cache->expects($this->at(1))
->method('get')
->with('element_info')
->will($this->returnValue(FALSE));
$this->cache->expects($this->at(2))
->method('set')
->with('element_info');
$this->cache->expects($this->at(3))
->method('set')
->with('element_info_build:test');
$this->assertEquals($expected_info, $this->elementInfo->getInfo($type));
}
/**
* Provides tests data for getInfo.
*
* @return array
*/
public function providerTestGetInfo() {
$data = array();
// Provide an element and expect it is returned.
$data[] = array(
'page',
array(
'#type' => 'page',
'#theme' => 'page',
'#defaults_loaded' => TRUE,
),
array('page' => array(
'#theme' => 'page',
)),
);
// Provide an element but request an non existent one.
$data[] = array(
'form',
array(
'#defaults_loaded' => TRUE,
),
array('page' => array(
'#theme' => 'page',
)),
);
// Provide an element and alter it to ensure it is altered.
$data[] = array(
'page',
array(
'#type' => 'page',
'#theme' => 'page',
'#number' => 597219,
'#defaults_loaded' => TRUE,
),
array('page' => array(
'#theme' => 'page',
)),
function ($alter_name, array &$info) {
$info['page']['#number'] = 597219;
}
);
return $data;
}
/**
* Tests the getInfo() method when render element plugins are used.
*
@ -170,10 +75,6 @@ class ElementInfoManagerTest extends UnitTestCase {
* @dataProvider providerTestGetInfoElementPlugin
*/
public function testGetInfoElementPlugin($plugin_class, $expected_info) {
$this->moduleHandler->expects($this->once())
->method('invokeAll')
->with('element_info')
->willReturn(array());
$this->moduleHandler->expects($this->once())
->method('alter')
->with('element_info', $this->anything())

View file

@ -38,9 +38,6 @@ class RendererBubblingTest extends RendererTestBase {
$this->setUpRequest();
$this->setupMemoryCache();
$this->elementInfo->expects($this->any())
->method('getInfo')
->willReturn([]);
$this->cacheContextsManager->expects($this->any())
->method('convertTokensToKeys')
->willReturnArgument(0);
@ -302,7 +299,7 @@ class RendererBubblingTest extends RendererTestBase {
* Tests the self-healing of the redirect with conditional cache contexts.
*/
public function testConditionalCacheContextBubblingSelfHealing() {
global $current_user_role;
$current_user_role = &$this->currentUserRole;
$this->setUpRequest();
$this->setupMemoryCache();
@ -319,8 +316,7 @@ class RendererBubblingTest extends RendererTestBase {
'tags' => ['b'],
],
'grandchild' => [
'#access_callback' => function () {
global $current_user_role;
'#access_callback' => function() use (&$current_user_role) {
// Only role A cannot access this subtree.
return $current_user_role !== 'A';
},
@ -331,8 +327,7 @@ class RendererBubblingTest extends RendererTestBase {
'max-age' => 1800,
],
'grandgrandchild' => [
'#access_callback' => function () {
global $current_user_role;
'#access_callback' => function () use (&$current_user_role) {
// Only role C can access this subtree.
return $current_user_role === 'C';
},

View file

@ -8,9 +8,9 @@
namespace Drupal\Tests\Core\Render;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Render\Element;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Render\SafeString;
/**
* @coversDefaultClass \Drupal\Core\Render\Renderer
@ -37,13 +37,24 @@ class RendererPlaceholdersTest extends RendererTestBase {
* Also, different types:
* - A) automatically generated placeholder
* - 1) manually triggered (#create_placeholder = TRUE)
* - 2) automatically triggered (based on max-age = 0 in its subtree)
* - 2) automatically triggered (based on max-age = 0 at the top level)
* - 3) automatically triggered (based on high cardinality cache contexts at
* the top level)
* - 4) automatically triggered (based on high-invalidation frequency cache
* tags at the top level)
* - 5) automatically triggered (based on max-age = 0 in its subtree, i.e.
* via bubbling)
* - 6) automatically triggered (based on high cardinality cache contexts in
* its subtree, i.e. via bubbling)
* - 7) automatically triggered (based on high-invalidation frequency cache
* tags in its subtree, i.e. via bubbling)
* - B) manually generated placeholder
*
* So, in total 2*3 = 6 permutations.
* So, in total 2*5 = 10 permutations.
*
* @todo Case A2 is not yet supported by core. So that makes for only 4
* permutations currently.
* @todo Cases A5, A6 and A7 are not yet supported by core. So that makes for
* only 10 permutations currently, instead of 16. That will be done in
* https://www.drupal.org/node/2543334
*
* @return array
*/
@ -52,23 +63,23 @@ class RendererPlaceholdersTest extends RendererTestBase {
$generate_placeholder_markup = function($cache_keys = NULL) use ($args) {
$token_render_array = [
'#cache' => [],
'#lazy_builder' => ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', $args],
];
if (is_array($cache_keys)) {
$token_render_array['#cache']['keys'] = $cache_keys;
}
else {
unset($token_render_array['#cache']);
}
$token = hash('sha1', serialize($token_render_array));
return SafeMarkup::format('<drupal-render-placeholder callback="@callback" arguments="@arguments" token="@token"></drupal-render-placeholder>', [
'@callback' => 'Drupal\Tests\Core\Render\PlaceholdersTest::callback',
'@arguments' => '0=' . $args[0],
'@token' => $token,
]);
$token = hash('crc32b', serialize($token_render_array));
// \Drupal\Core\Render\SafeString::create() is necessary as the render
// system would mangle this markup. As this is exactly what happens at
// runtime this is a valid use-case.
return SafeString::create('<drupal-render-placeholder callback="Drupal\Tests\Core\Render\PlaceholdersTest::callback" arguments="' . '0=' . $args[0] . '" token="' . $token . '"></drupal-render-placeholder>');
};
$extract_placeholder_render_array = function ($placeholder_render_array) {
return array_intersect_key($placeholder_render_array, ['#lazy_builder' => TRUE, '#cache' => TRUE]);
};
// Note the presence of '#create_placeholder'.
$base_element_a1 = [
'#attached' => [
'drupalSettings' => [
@ -83,9 +94,55 @@ class RendererPlaceholdersTest extends RendererTestBase {
'#lazy_builder' => ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', $args],
],
];
// Note the absence of '#create_placeholder', presence of max-age=0 at the
// top level.
$base_element_a2 = [
// @todo, see docblock
'#attached' => [
'drupalSettings' => [
'foo' => 'bar',
],
],
'placeholder' => [
'#cache' => [
'contexts' => [],
'max-age' => 0,
],
'#lazy_builder' => ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', $args],
],
];
// Note the absence of '#create_placeholder', presence of high cardinality
// cache context at the top level.
$base_element_a3 = [
'#attached' => [
'drupalSettings' => [
'foo' => 'bar',
],
],
'placeholder' => [
'#cache' => [
'contexts' => ['user'],
],
'#lazy_builder' => ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', $args],
],
];
// Note the absence of '#create_placeholder', presence of high-invalidation
// frequency cache tag at the top level.
$base_element_a4 = [
'#attached' => [
'drupalSettings' => [
'foo' => 'bar',
],
],
'placeholder' => [
'#cache' => [
'contexts' => [],
'tags' => ['current-temperature'],
],
'#lazy_builder' => ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', $args],
],
];
// Note the absence of '#create_placeholder', but the presence of
// '#attached[placeholders]'.
$base_element_b = [
'#markup' => $generate_placeholder_markup(),
'#attached' => [
@ -93,8 +150,7 @@ class RendererPlaceholdersTest extends RendererTestBase {
'foo' => 'bar',
],
'placeholders' => [
$generate_placeholder_markup() => [
'#cache' => [],
(string) $generate_placeholder_markup() => [
'#lazy_builder' => ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', $args],
],
],
@ -109,9 +165,11 @@ class RendererPlaceholdersTest extends RendererTestBase {
// - automatically created, but manually triggered (#create_placeholder = TRUE)
// - uncacheable
$element_without_cache_keys = $base_element_a1;
$expected_placeholder_render_array = $extract_placeholder_render_array($base_element_a1['placeholder']);
$cases[] = [
$element_without_cache_keys,
$args,
$expected_placeholder_render_array,
FALSE,
[],
];
@ -121,9 +179,11 @@ class RendererPlaceholdersTest extends RendererTestBase {
// - cacheable
$element_with_cache_keys = $base_element_a1;
$element_with_cache_keys['placeholder']['#cache']['keys'] = $keys;
$expected_placeholder_render_array['#cache']['keys'] = $keys;
$cases[] = [
$element_with_cache_keys,
$args,
$expected_placeholder_render_array,
$keys,
[
'#markup' => '<p>This is a rendered placeholder!</p>',
@ -141,31 +201,149 @@ class RendererPlaceholdersTest extends RendererTestBase {
];
// Case three: render array that has a placeholder that is:
// - manually created
// - automatically created, and automatically triggered due to max-age=0
// - uncacheable
$x = $base_element_b;
unset($x['#attached']['placeholders'][$generate_placeholder_markup()]['#cache']);
$element_without_cache_keys = $base_element_a2;
$expected_placeholder_render_array = $extract_placeholder_render_array($base_element_a2['placeholder']);
$cases[] = [
$x,
$element_without_cache_keys,
$args,
$expected_placeholder_render_array,
FALSE,
[],
];
// Case four: render array that has a placeholder that is:
// - automatically created, but automatically triggered due to max-age=0
// - cacheable
$element_with_cache_keys = $base_element_a2;
$element_with_cache_keys['placeholder']['#cache']['keys'] = $keys;
$expected_placeholder_render_array['#cache']['keys'] = $keys;
$cases[] = [
$element_with_cache_keys,
$args,
$expected_placeholder_render_array,
FALSE,
[]
];
// Case five: render array that has a placeholder that is:
// - automatically created, and automatically triggered due to high
// cardinality cache contexts
// - uncacheable
$element_without_cache_keys = $base_element_a3;
$expected_placeholder_render_array = $extract_placeholder_render_array($base_element_a3['placeholder']);
$cases[] = [
$element_without_cache_keys,
$args,
$expected_placeholder_render_array,
FALSE,
[],
];
// Case six: render array that has a placeholder that is:
// - automatically created, and automatically triggered due to high
// cardinality cache contexts
// - cacheable
$element_with_cache_keys = $base_element_a3;
$element_with_cache_keys['placeholder']['#cache']['keys'] = $keys;
$expected_placeholder_render_array['#cache']['keys'] = $keys;
// The CID parts here consist of the cache keys plus the 'user' cache
// context, which in this unit test is simply the given cache context token,
// see \Drupal\Tests\Core\Render\RendererTestBase::setUp().
$cid_parts = array_merge($keys, ['user']);
$cases[] = [
$element_with_cache_keys,
$args,
$expected_placeholder_render_array,
$cid_parts,
[
'#markup' => '<p>This is a rendered placeholder!</p>',
'#attached' => [
'drupalSettings' => [
'dynamic_animal' => $args[0],
],
],
'#cache' => [
'contexts' => ['user'],
'tags' => [],
'max-age' => Cache::PERMANENT,
],
],
];
// Case seven: render array that has a placeholder that is:
// - automatically created, and automatically triggered due to high
// invalidation frequency cache tags
// - uncacheable
$element_without_cache_keys = $base_element_a4;
$expected_placeholder_render_array = $extract_placeholder_render_array($base_element_a4['placeholder']);
$cases[] = [
$element_without_cache_keys,
$args,
$expected_placeholder_render_array,
FALSE,
[],
];
// Case eight: render array that has a placeholder that is:
// - automatically created, and automatically triggered due to high
// invalidation frequency cache tags
// - cacheable
$element_with_cache_keys = $base_element_a4;
$element_with_cache_keys['placeholder']['#cache']['keys'] = $keys;
$expected_placeholder_render_array['#cache']['keys'] = $keys;
$cases[] = [
$element_with_cache_keys,
$args,
$expected_placeholder_render_array,
$keys,
[
'#markup' => '<p>This is a rendered placeholder!</p>',
'#attached' => [
'drupalSettings' => [
'dynamic_animal' => $args[0],
],
],
'#cache' => [
'contexts' => [],
'tags' => ['current-temperature'],
'max-age' => Cache::PERMANENT,
],
],
];
// Case nine: render array that has a placeholder that is:
// - manually created
// - uncacheable
$x = $base_element_b;
$expected_placeholder_render_array = $x['#attached']['placeholders'][(string) $generate_placeholder_markup()];
unset($x['#attached']['placeholders'][(string) $generate_placeholder_markup()]['#cache']);
$cases[] = [
$x,
$args,
$expected_placeholder_render_array,
FALSE,
[],
];
// Case ten: render array that has a placeholder that is:
// - manually created
// - cacheable
$x = $base_element_b;
$x['#markup'] = $generate_placeholder_markup($keys);
$x['#markup'] = $placeholder_markup = $generate_placeholder_markup($keys);
$placeholder_markup = (string) $placeholder_markup;
$x['#attached']['placeholders'] = [
$generate_placeholder_markup($keys) => [
$placeholder_markup => [
'#lazy_builder' => ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', $args],
'#cache' => ['keys' => $keys],
],
];
$expected_placeholder_render_array = $x['#attached']['placeholders'][$placeholder_markup];
$cases[] = [
$x,
$args,
$expected_placeholder_render_array,
$keys,
[
'#markup' => '<p>This is a rendered placeholder!</p>',
@ -224,8 +402,8 @@ class RendererPlaceholdersTest extends RendererTestBase {
*
* @dataProvider providerPlaceholders
*/
public function testUncacheableParent($element, $args, $placeholder_cid_keys, array $placeholder_expected_render_cache_array) {
if ($placeholder_cid_keys) {
public function testUncacheableParent($element, $args, array $expected_placeholder_render_array, $placeholder_cid_parts, array $placeholder_expected_render_cache_array) {
if ($placeholder_cid_parts) {
$this->setupMemoryCache();
}
else {
@ -244,7 +422,7 @@ class RendererPlaceholdersTest extends RendererTestBase {
'dynamic_animal' => $args[0],
];
$this->assertSame($element['#attached']['drupalSettings'], $expected_js_settings, '#attached is modified; both the original JavaScript setting and the one added by the placeholder #lazy_builder callback exist.');
$this->assertPlaceholderRenderCache($placeholder_cid_keys, $placeholder_expected_render_cache_array);
$this->assertPlaceholderRenderCache($placeholder_cid_parts, $placeholder_expected_render_cache_array);
}
/**
@ -256,26 +434,13 @@ class RendererPlaceholdersTest extends RendererTestBase {
*
* @dataProvider providerPlaceholders
*/
public function testCacheableParent($test_element, $args, $placeholder_cid_keys, array $placeholder_expected_render_cache_array) {
public function testCacheableParent($test_element, $args, array $expected_placeholder_render_array, $placeholder_cid_parts, array $placeholder_expected_render_cache_array) {
$element = $test_element;
$this->setupMemoryCache();
$this->setUpRequest('GET');
// Generate the expected placeholder render array, so that we can generate
// the expected placeholder markup.
$expected_placeholder_render_array = [];
// When there was a child element that created a placeholder, the Renderer
// automatically initializes #cache[contexts].
if (Element::children($test_element)) {
$expected_placeholder_render_array['#cache']['contexts'] = [];
}
// When the placeholder itself is cacheable, its cache keys are present.
if ($placeholder_cid_keys) {
$expected_placeholder_render_array['#cache']['keys'] = $placeholder_cid_keys;
}
$expected_placeholder_render_array['#lazy_builder'] = ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', $args];
$token = hash('sha1', serialize($expected_placeholder_render_array));
$token = hash('crc32b', serialize($expected_placeholder_render_array));
$expected_placeholder_markup = '<drupal-render-placeholder callback="Drupal\Tests\Core\Render\PlaceholdersTest::callback" arguments="0=' . $args[0] . '" token="' . $token . '"></drupal-render-placeholder>';
$this->assertSame($expected_placeholder_markup, Html::normalize($expected_placeholder_markup), 'Placeholder unaltered by Html::normalize() which is used by FilterHtmlCorrector.');
@ -291,7 +456,7 @@ class RendererPlaceholdersTest extends RendererTestBase {
'dynamic_animal' => $args[0],
];
$this->assertSame($element['#attached']['drupalSettings'], $expected_js_settings, '#attached is modified; both the original JavaScript setting and the one added by the placeholder #lazy_builder callback exist.');
$this->assertPlaceholderRenderCache($placeholder_cid_keys, $placeholder_expected_render_cache_array);
$this->assertPlaceholderRenderCache($placeholder_cid_parts, $placeholder_expected_render_cache_array);
// GET request: validate cached data.
$cached_element = $this->memoryCache->get('placeholder_test_GET')->data;
@ -434,7 +599,9 @@ class RendererPlaceholdersTest extends RendererTestBase {
'null' => NULL,
]];
$this->renderer->renderRoot($element);
$result = $this->renderer->renderRoot($element);
$this->assertInstanceOf('\Drupal\Core\Render\SafeString', $result);
$this->assertEquals('<p>This is a rendered placeholder!</p>', (string) $result);
}
/**
@ -521,10 +688,6 @@ class RendererPlaceholdersTest extends RendererTestBase {
$this->cacheContextsManager->expects($this->any())
->method('convertTokensToKeys')
->willReturnArgument(0);
$this->elementInfo->expects($this->any())
->method('getInfo')
->with('details')
->willReturn(['#theme_wrappers' => ['details']]);
$this->controllerResolver->expects($this->any())
->method('getControllerFromDefinition')
->willReturnArgument(0);

View file

@ -35,6 +35,18 @@ class RendererTest extends RendererTestBase {
'#children' => '',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Reset the static list of SafeStrings to prevent bleeding between tests.
$reflected_class = new \ReflectionClass('\Drupal\Component\Utility\SafeMarkup');
$reflected_property = $reflected_class->getProperty('safeStrings');
$reflected_property->setAccessible(true);
$reflected_property->setValue([]);
}
/**
* @covers ::render
* @covers ::doRender
@ -47,7 +59,15 @@ class RendererTest extends RendererTestBase {
$setup_code();
}
$this->assertSame($expected, (string) $this->renderer->renderRoot($build));
if (isset($build['#markup'])) {
$this->assertFalse(SafeMarkup::isSafe($build['#markup']), 'The #markup value is not marked safe before rendering.');
}
$render_output = $this->renderer->renderRoot($build);
$this->assertSame($expected, (string) $render_output);
if ($render_output !== '') {
$this->assertTrue(SafeMarkup::isSafe($render_output), 'Output of render is marked safe.');
$this->assertTrue(SafeMarkup::isSafe($build['#markup']), 'The #markup value is marked safe after rendering.');
}
}
/**
@ -80,6 +100,19 @@ class RendererTest extends RendererTestBase {
$data[] = [[
'#markup' => 'foo',
], 'foo'];
// Basic #plain_text based renderable array.
$data[] = [[
'#plain_text' => 'foo',
], 'foo'];
// Mixing #plain_text and #markup based renderable array.
$data[] = [[
'#plain_text' => '<em>foo</em>',
'#markup' => 'bar',
], '&lt;em&gt;foo&lt;/em&gt;'];
// Safe strings in #plain_text are are still escaped.
$data[] = [[
'#plain_text' => SafeString::create('<em>foo</em>'),
], '&lt;em&gt;foo&lt;/em&gt;'];
// Renderable child element.
$data[] = [[
'child' => ['#markup' => 'bar'],
@ -88,6 +121,22 @@ class RendererTest extends RendererTestBase {
$data[] = [[
'child' => ['#markup' => "This is <script>alert('XSS')</script> test"],
], "This is alert('XSS') test"];
// XSS filtering test.
$data[] = [[
'child' => ['#markup' => "This is <script>alert('XSS')</script> test", '#allowed_tags' => ['script']],
], "This is <script>alert('XSS')</script> test"];
// XSS filtering test.
$data[] = [[
'child' => ['#markup' => "This is <script><em>alert('XSS')</em></script> <strong>test</strong>", '#allowed_tags' => ['em', 'strong']],
], "This is <em>alert('XSS')</em> <strong>test</strong>"];
// Html escaping test.
$data[] = [[
'child' => ['#plain_text' => "This is <script><em>alert('XSS')</em></script> <strong>test</strong>"],
], "This is &lt;script&gt;&lt;em&gt;alert(&#039;XSS&#039;)&lt;/em&gt;&lt;/script&gt; &lt;strong&gt;test&lt;/strong&gt;"];
// XSS filtering by default test.
$data[] = [[
'child' => ['#markup' => "This is <script><em>alert('XSS')</em></script> <strong>test</strong>"],
], "This is <em>alert('XSS')</em> <strong>test</strong>"];
// Ensure non-XSS tags are not filtered out.
$data[] = [[
'child' => ['#markup' => "This is <strong><script>alert('not a giraffe')</script></strong> test"],
@ -150,10 +199,6 @@ class RendererTest extends RendererTestBase {
$attributes = new Attribute(['href' => $vars['#url']] + (isset($vars['#attributes']) ? $vars['#attributes'] : []));
return '<a' . (string) $attributes . '>' . $vars['#title'] . '</a>';
});
$this->elementInfo->expects($this->atLeastOnce())
->method('getInfo')
->with('link')
->willReturn(['#theme' => 'link']);
};
$data[] = [$build, '<div class="baz"><a href="https://www.drupal.org" id="foo">bar</a></div>' . "\n", $setup_code_type_link];

View file

@ -79,6 +79,13 @@ class RendererTestBase extends UnitTestCase {
*/
protected $memoryCache;
/**
* The simulated "current" user role, for use in tests with cache contexts.
*
* @var string
*/
protected $currentUserRole;
/**
* The mocked renderer configuration.
*
@ -89,6 +96,11 @@ class RendererTestBase extends UnitTestCase {
'languages:language_interface',
'theme',
],
'auto_placeholder_conditions' => [
'max-age' => 0,
'contexts' => ['session', 'user'],
'tags' => ['current-temperature'],
],
];
/**
@ -100,6 +112,22 @@ class RendererTestBase extends UnitTestCase {
$this->controllerResolver = $this->getMock('Drupal\Core\Controller\ControllerResolverInterface');
$this->themeManager = $this->getMock('Drupal\Core\Theme\ThemeManagerInterface');
$this->elementInfo = $this->getMock('Drupal\Core\Render\ElementInfoManagerInterface');
$this->elementInfo->expects($this->any())
->method('getInfo')
->willReturnCallback(function ($type) {
switch ($type) {
case 'details':
$info = ['#theme_wrappers' => ['details']];
break;
case 'link':
$info = ['#theme' => 'link'];
break;
default:
$info = [];
}
$info['#defaults_loaded'] = TRUE;
return $info;
});
$this->requestStack = new RequestStack();
$request = new Request();
$request->server->set('REQUEST_TIME', $_SERVER['REQUEST_TIME']);
@ -108,10 +136,10 @@ class RendererTestBase extends UnitTestCase {
$this->cacheContextsManager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
->disableOriginalConstructor()
->getMock();
$current_user_role = &$this->currentUserRole;
$this->cacheContextsManager->expects($this->any())
->method('convertTokensToKeys')
->willReturnCallback(function($context_tokens) {
global $current_user_role;
->willReturnCallback(function($context_tokens) use (&$current_user_role) {
$keys = [];
foreach ($context_tokens as $context_id) {
switch ($context_id) {

View file

@ -8,6 +8,8 @@
namespace Drupal\Tests\Core\Route;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Drupal\Core\DependencyInjection\Container;
use Drupal\Core\Session\UserSession;
use Drupal\Tests\UnitTestCase;
use Drupal\user\Access\RoleAccessCheck;
@ -143,6 +145,11 @@ class RoleAccessCheckTest extends UnitTestCase {
* @dataProvider roleAccessProvider
*/
public function testRoleAccess($path, $grant_accounts, $deny_accounts) {
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class)->reveal();
$container = new Container();
$container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($container);
$role_access_check = new RoleAccessCheck();
$collection = $this->getTestRouteCollection();

View file

@ -41,13 +41,21 @@ class RoutePreloaderTest extends UnitTestCase {
*/
protected $preloader;
/**
* The mocked cache.
*
* @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $cache;
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->routeProvider = $this->getMock('Drupal\Core\Routing\PreloadableRouteProviderInterface');
$this->state = $this->getMock('\Drupal\Core\State\StateInterface');
$this->preloader = new RoutePreloader($this->routeProvider, $this->state);
$this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
$this->preloader = new RoutePreloader($this->routeProvider, $this->state, $this->cache);
}
/**

View file

@ -61,6 +61,13 @@ class PermissionsHashGeneratorTest extends UnitTestCase {
*/
protected $cache;
/**
* The mocked cache backend.
*
* @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $staticCache;
/**
* The permission hash class being tested.
*
@ -138,12 +145,15 @@ class PermissionsHashGeneratorTest extends UnitTestCase {
$this->cache = $this->getMockBuilder('Drupal\Core\Cache\CacheBackendInterface')
->disableOriginalConstructor()
->getMock();
$this->staticCache = $this->getMockBuilder('Drupal\Core\Cache\CacheBackendInterface')
->disableOriginalConstructor()
->getMock();
$this->permissionsHash = new PermissionsHashGenerator($this->privateKey, $this->cache);
$this->permissionsHash = new PermissionsHashGenerator($this->privateKey, $this->cache, $this->staticCache);
}
/**
* Tests the generate() method.
* @covers ::generate
*/
public function testGenerate() {
// Ensure that the super user (user 1) always gets the same hash.
@ -162,15 +172,23 @@ class PermissionsHashGeneratorTest extends UnitTestCase {
}
/**
* Tests the generate method with cache returned.
* @covers ::generate
*/
public function testGenerateCache() {
public function testGeneratePersistentCache() {
// Set expectations for the mocked cache backend.
$expected_cid = 'user_permissions_hash:administrator,authenticated';
$mock_cache = new \stdClass();
$mock_cache->data = 'test_hash_here';
$this->staticCache->expects($this->once())
->method('get')
->with($expected_cid)
->will($this->returnValue(FALSE));
$this->staticCache->expects($this->once())
->method('set')
->with($expected_cid, $this->isType('string'));
$this->cache->expects($this->once())
->method('get')
->with($expected_cid)
@ -181,6 +199,31 @@ class PermissionsHashGeneratorTest extends UnitTestCase {
$this->permissionsHash->generate($this->account2);
}
/**
* @covers ::generate
*/
public function testGenerateStaticCache() {
// Set expectations for the mocked cache backend.
$expected_cid = 'user_permissions_hash:administrator,authenticated';
$mock_cache = new \stdClass();
$mock_cache->data = 'test_hash_here';
$this->staticCache->expects($this->once())
->method('get')
->with($expected_cid)
->will($this->returnValue($mock_cache));
$this->staticCache->expects($this->never())
->method('set');
$this->cache->expects($this->never())
->method('get');
$this->cache->expects($this->never())
->method('set');
$this->permissionsHash->generate($this->account2);
}
/**
* Tests the generate method with no cache returned.
*/
@ -188,6 +231,14 @@ class PermissionsHashGeneratorTest extends UnitTestCase {
// Set expectations for the mocked cache backend.
$expected_cid = 'user_permissions_hash:administrator,authenticated';
$this->staticCache->expects($this->once())
->method('get')
->with($expected_cid)
->will($this->returnValue(FALSE));
$this->staticCache->expects($this->once())
->method('set')
->with($expected_cid, $this->isType('string'));
$this->cache->expects($this->once())
->method('get')
->with($expected_cid)

View file

@ -0,0 +1,142 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\StackMiddleware\NegotiationMiddlewareTest.
*/
namespace Drupal\Tests\Core\StackMiddleware;
use Drupal\Core\StackMiddleware\NegotiationMiddleware;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* @coversDefaultClass \Drupal\Core\StackMiddleware\NegotiationMiddleware
* @group NegotiationMiddleware
*/
class NegotiationMiddlewareTest extends UnitTestCase {
/**
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
*/
protected $app;
/**
* @var \Drupal\Tests\Core\StackMiddleware\StubNegotiationMiddleware
*/
protected $contentNegotiation;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->app = $this->prophesize(HttpKernelInterface::class);
$this->contentNegotiation = new StubNegotiationMiddleware($this->app->reveal());
}
/**
* Tests the getContentType() method with AJAX iframe upload.
*
* @covers ::getContentType
*/
public function testAjaxIframeUpload() {
$request = new Request();
$request->attributes->set('ajax_iframe_upload', '1');
$this->assertSame('iframeupload', $this->contentNegotiation->getContentType($request));
}
/**
* Tests the specifying a format via query parameters gets used.
*
* @covers ::getContentType
*/
public function testFormatViaQueryParameter() {
$request = new Request();
$request->query->set('_format', 'bob');
$this->assertSame('bob', $this->contentNegotiation->getContentType($request));
}
/**
* Tests the getContentType() method when no priority format is found.
*
* @covers ::getContentType
*/
public function testUnknowContentTypeReturnsHtmlByDefault() {
$request = new Request();
$this->assertSame('html', $this->contentNegotiation->getContentType($request));
}
/**
* Tests the getContentType() method when no priority format is found but it's an AJAX request.
*
* @covers ::getContentType
*/
public function testUnknowContentTypeButAjaxRequest() {
$request = new Request();
$request->headers->set('X-Requested-With', 'XMLHttpRequest');
$this->assertSame('html', $this->contentNegotiation->getContentType($request));
}
/**
* Test that handle() correctly hands off to sub application.
*
* @covers ::handle
*/
public function testHandle() {
$request = $this->prophesize(Request::class);
// Default empty format list should not set any formats.
$request->setFormat()->shouldNotBeCalled();
// Request format will be set with default format.
$request->setRequestFormat('html')->shouldBeCalled();
// Some getContentType calls we don't really care about but have to mock.
$request->get('ajax_iframe_upload', false)->shouldBeCalled();
$request_mock = $request->reveal();
$request_mock->query = new ParameterBag([]);
// Calling kernel app with default arguments.
$this->app->handle($request_mock, HttpKernelInterface::MASTER_REQUEST, TRUE)
->shouldBeCalled();
$this->contentNegotiation->handle($request_mock);
// Calling kernel app with specified arguments.
$this->app->handle($request_mock, HttpKernelInterface::SUB_REQUEST, FALSE)
->shouldBeCalled();
$this->contentNegotiation->handle($request_mock, HttpKernelInterface::SUB_REQUEST, FALSE);
}
/**
* @covers ::registerFormat
*/
public function testSetFormat() {
$request = $this->prophesize(Request::class);
// Default empty format list should not set any formats.
$request->setFormat('david', 'geeky/david')->shouldBeCalled();
// Some calls we don't care about.
$request->setRequestFormat('html')->shouldBeCalled();
$request->get('ajax_iframe_upload', false)->shouldBeCalled();
$request_mock = $request->reveal();
$request_mock->query = new ParameterBag([]);
// Trigger handle.
$this->contentNegotiation->registerFormat('david', 'geeky/david');
$this->contentNegotiation->handle($request_mock);
}
}
class StubNegotiationMiddleware extends NegotiationMiddleware {
public function getContentType(Request $request) { return parent::getContentType($request); }
}

View file

@ -7,6 +7,9 @@
namespace Drupal\Tests\Core\Template;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Template\TwigEnvironment;
use Drupal\Core\Template\TwigExtension;
use Drupal\Tests\UnitTestCase;
@ -124,6 +127,31 @@ class TwigExtensionTest extends UnitTestCase {
$this->assertSame('&lt;script&gt;alert(&#039;here&#039;);&lt;/script&gt;', $twig_extension->escapeFilter($twig, $string_object, 'html', 'UTF-8', TRUE));
}
/**
* @covers ::safeJoin
*/
public function testSafeJoin() {
$renderer = $this->prophesize(RendererInterface::class);
$renderer->render(['#markup' => '<strong>will be rendered</strong>', '#printed' => FALSE])->willReturn('<strong>will be rendered</strong>');
$renderer = $renderer->reveal();
$twig_extension = new TwigExtension($renderer);
$twig_environment = $this->prophesize(TwigEnvironment::class)->reveal();
// Simulate t().
$string = '<em>will be markup</em>';
SafeMarkup::setMultiple([$string => ['html' => TRUE]]);
$items = [
'<em>will be escaped</em>',
$string,
['#markup' => '<strong>will be rendered</strong>']
];
$result = $twig_extension->safeJoin($twig_environment, $items, '<br/>');
$this->assertEquals('&lt;em&gt;will be escaped&lt;/em&gt;<br/><em>will be markup</em><br/><strong>will be rendered</strong>', $result);
}
}
class TwigExtensionTestString {

View file

@ -105,6 +105,9 @@ class RegistryTest extends UnitTestCase {
->method('getImplementations')
->with('theme')
->will($this->returnValue(array('theme_test')));
$this->moduleHandler->expects($this->atLeastOnce())
->method('getModuleList')
->willReturn([]);
$registry = $this->registry->get();

View file

@ -8,7 +8,6 @@
namespace Drupal\Tests\Core\Transliteration;
use Drupal\Component\Utility\Random;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Transliteration\PhpTransliteration;
use Drupal\Tests\UnitTestCase;
@ -59,12 +58,7 @@ class PhpTransliterationTest extends UnitTestCase {
$transliteration = new PhpTransliteration(NULL, $module_handler);
$actual = $transliteration->transliterate($original, $langcode);
$this->assertSame($expected, $actual, SafeMarkup::format('@original transliteration to @actual is identical to @expected for language @langcode in service instance.', array(
'@original' => $printable,
'@langcode' => $langcode,
'@expected' => $expected,
'@actual' => $actual,
)));
$this->assertSame($expected, $actual, "'$printable' transliteration to '$actual' is identical to '$expected' for language '$langcode' in service instance.");
}
/**

View file

@ -7,10 +7,10 @@
namespace Drupal\Tests\Core\Utility {
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\GeneratedUrl;
use Drupal\Core\Language\Language;
use Drupal\Core\Link;
use Drupal\Core\Render\SafeString;
use Drupal\Core\Url;
use Drupal\Core\Utility\LinkGenerator;
use Drupal\Tests\UnitTestCase;
@ -372,11 +372,11 @@ class LinkGeneratorTest extends UnitTestCase {
), $result);
// Test that safe HTML is output inside the anchor tag unescaped. The
// SafeMarkup::set() call is an intentional unit test for the interaction
// between SafeMarkup and the LinkGenerator.
// SafeString::create() call is an intentional unit test for the interaction
// between SafeStringInterface and the LinkGenerator.
$url = new Url('test_route_5', array());
$url->setUrlGenerator($this->urlGenerator);
$result = $this->linkGenerator->generate(SafeMarkup::set('<em>HTML output</em>'), $url);
$result = $this->linkGenerator->generate(SafeString::create('<em>HTML output</em>'), $url);
$this->assertLink(array(
'attributes' => array('href' => '/test-route-5'),
'child' => array(