Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176
This commit is contained in:
commit
9921556621
13277 changed files with 1459781 additions and 0 deletions
568
core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php
Normal file
568
core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php
Normal file
|
@ -0,0 +1,568 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Access\AccessManagerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessCheckInterface;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Access\AccessManagerInterface;
|
||||
use Drupal\Core\Access\CheckProvider;
|
||||
use Drupal\Core\Routing\RouteMatch;
|
||||
use Drupal\Core\Access\AccessManager;
|
||||
use Drupal\Core\Access\DefaultAccessCheck;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\router_test\Access\DefinedTestAccessCheck;
|
||||
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\Routing\Exception\RouteNotFoundException;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Access\AccessManager
|
||||
* @group Access
|
||||
*/
|
||||
class AccessManagerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The dependency injection container.
|
||||
*
|
||||
* @var \Symfony\Component\DependencyInjection\ContainerBuilder
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* The collection of routes, which are tested.
|
||||
*
|
||||
* @var \Symfony\Component\Routing\RouteCollection
|
||||
*/
|
||||
protected $routeCollection;
|
||||
|
||||
/**
|
||||
* The access manager to test.
|
||||
*
|
||||
* @var \Drupal\Core\Access\AccessManager
|
||||
*/
|
||||
protected $accessManager;
|
||||
|
||||
/**
|
||||
* The route provider.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $routeProvider;
|
||||
|
||||
/**
|
||||
* The parameter converter.
|
||||
*
|
||||
* @var \Drupal\Core\ParamConverter\ParamConverterManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $paramConverter;
|
||||
|
||||
/**
|
||||
* The mocked account.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* The access arguments resolver.
|
||||
*
|
||||
* @var \Drupal\Core\Access\AccessArgumentsResolverFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $argumentsResolverFactory;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Access\CheckProvider
|
||||
*/
|
||||
protected $checkProvider;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->container = new ContainerBuilder();
|
||||
|
||||
$this->routeCollection = new RouteCollection();
|
||||
$this->routeCollection->add('test_route_1', new Route('/test-route-1'));
|
||||
$this->routeCollection->add('test_route_2', new Route('/test-route-2', array(), array('_access' => 'TRUE')));
|
||||
$this->routeCollection->add('test_route_3', new Route('/test-route-3', array(), array('_access' => 'FALSE')));
|
||||
$this->routeCollection->add('test_route_4', new Route('/test-route-4/{value}', array(), array('_access' => 'TRUE')));
|
||||
|
||||
$this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
|
||||
$map = array();
|
||||
foreach ($this->routeCollection->all() as $name => $route) {
|
||||
$map[] = array($name, array(), $route);
|
||||
}
|
||||
$map[] = array('test_route_4', array('value' => 'example'), $this->routeCollection->get('test_route_4'));
|
||||
$this->routeProvider->expects($this->any())
|
||||
->method('getRouteByName')
|
||||
->will($this->returnValueMap($map));
|
||||
|
||||
$map = array();
|
||||
$map[] = array('test_route_1', array(), '/test-route-1');
|
||||
$map[] = array('test_route_2', array(), '/test-route-2');
|
||||
$map[] = array('test_route_3', array(), '/test-route-3');
|
||||
$map[] = array('test_route_4', array('value' => 'example'), '/test-route-4/example');
|
||||
|
||||
$this->paramConverter = $this->getMock('Drupal\Core\ParamConverter\ParamConverterManagerInterface');
|
||||
|
||||
$this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
|
||||
$this->currentUser = $this->getMock('Drupal\Core\Session\AccountInterface');
|
||||
$this->argumentsResolverFactory = $this->getMock('Drupal\Core\Access\AccessArgumentsResolverFactoryInterface');
|
||||
$this->checkProvider = new CheckProvider();
|
||||
$this->checkProvider->setContainer($this->container);
|
||||
|
||||
$this->accessManager = new AccessManager($this->routeProvider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests \Drupal\Core\Access\AccessManager::setChecks().
|
||||
*/
|
||||
public function testSetChecks() {
|
||||
// Check setChecks without any access checker defined yet.
|
||||
$this->checkProvider->setChecks($this->routeCollection);
|
||||
|
||||
foreach ($this->routeCollection->all() as $route) {
|
||||
$this->assertNull($route->getOption('_access_checks'));
|
||||
}
|
||||
|
||||
$this->setupAccessChecker();
|
||||
|
||||
$this->checkProvider->setChecks($this->routeCollection);
|
||||
|
||||
$this->assertEquals($this->routeCollection->get('test_route_1')->getOption('_access_checks'), NULL);
|
||||
$this->assertEquals($this->routeCollection->get('test_route_2')->getOption('_access_checks'), array('test_access_default'));
|
||||
$this->assertEquals($this->routeCollection->get('test_route_3')->getOption('_access_checks'), array('test_access_default'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests setChecks with a dynamic access checker.
|
||||
*/
|
||||
public function testSetChecksWithDynamicAccessChecker() {
|
||||
// Setup the access manager.
|
||||
$this->accessManager = new AccessManager($this->routeProvider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider);
|
||||
|
||||
// Setup the dynamic access checker.
|
||||
$access_check = $this->getMock('Drupal\Tests\Core\Access\TestAccessCheckInterface');
|
||||
$this->container->set('test_access', $access_check);
|
||||
$this->checkProvider->addCheckService('test_access', 'access');
|
||||
|
||||
$route = new Route('/test-path', array(), array('_foo' => '1', '_bar' => '1'));
|
||||
$route2 = new Route('/test-path', array(), array('_foo' => '1', '_bar' => '2'));
|
||||
$collection = new RouteCollection();
|
||||
$collection->add('test_route', $route);
|
||||
$collection->add('test_route2', $route2);
|
||||
|
||||
$access_check->expects($this->exactly(2))
|
||||
->method('applies')
|
||||
->with($this->isInstanceOf('Symfony\Component\Routing\Route'))
|
||||
->will($this->returnCallback(function (Route $route) {
|
||||
return $route->getRequirement('_bar') == 2;
|
||||
}));
|
||||
|
||||
$this->checkProvider->setChecks($collection);
|
||||
$this->assertEmpty($route->getOption('_access_checks'));
|
||||
$this->assertEquals(array('test_access'), $route2->getOption('_access_checks'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests \Drupal\Core\Access\AccessManager::check().
|
||||
*/
|
||||
public function testCheck() {
|
||||
$route_matches = [];
|
||||
|
||||
// Construct route match objects.
|
||||
foreach ($this->routeCollection->all() as $route_name => $route) {
|
||||
$route_matches[$route_name] = new RouteMatch($route_name, $route, [], []);
|
||||
}
|
||||
|
||||
// Check route access without any access checker defined yet.
|
||||
foreach ($route_matches as $route_match) {
|
||||
$this->assertEquals(FALSE, $this->accessManager->check($route_match, $this->account));
|
||||
$this->assertEquals(AccessResult::neutral(), $this->accessManager->check($route_match, $this->account, NULL, TRUE));
|
||||
}
|
||||
|
||||
$this->setupAccessChecker();
|
||||
|
||||
// An access checker got setup, but the routes haven't been setup using
|
||||
// setChecks.
|
||||
foreach ($route_matches as $route_match) {
|
||||
$this->assertEquals(FALSE, $this->accessManager->check($route_match, $this->account));
|
||||
$this->assertEquals(AccessResult::neutral(), $this->accessManager->check($route_match, $this->account, NULL, TRUE));
|
||||
}
|
||||
|
||||
// Now applicable access checks have been saved on each route object.
|
||||
$this->checkProvider->setChecks($this->routeCollection);
|
||||
$this->setupAccessArgumentsResolverFactory();
|
||||
|
||||
$this->assertEquals(FALSE, $this->accessManager->check($route_matches['test_route_1'], $this->account));
|
||||
$this->assertEquals(TRUE, $this->accessManager->check($route_matches['test_route_2'], $this->account));
|
||||
$this->assertEquals(FALSE, $this->accessManager->check($route_matches['test_route_3'], $this->account));
|
||||
$this->assertEquals(TRUE, $this->accessManager->check($route_matches['test_route_4'], $this->account));
|
||||
$this->assertEquals(AccessResult::neutral(), $this->accessManager->check($route_matches['test_route_1'], $this->account, NULL, TRUE));
|
||||
$this->assertEquals(AccessResult::allowed(), $this->accessManager->check($route_matches['test_route_2'], $this->account, NULL, TRUE));
|
||||
$this->assertEquals(AccessResult::forbidden(), $this->accessManager->check($route_matches['test_route_3'], $this->account, NULL, TRUE));
|
||||
$this->assertEquals(AccessResult::allowed(), $this->accessManager->check($route_matches['test_route_4'], $this->account, NULL, TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests \Drupal\Core\Access\AccessManager::check() with no account specified.
|
||||
*
|
||||
* @covers ::check
|
||||
*/
|
||||
public function testCheckWithNullAccount() {
|
||||
$this->setupAccessChecker();
|
||||
$this->checkProvider->setChecks($this->routeCollection);
|
||||
|
||||
$route = $this->routeCollection->get('test_route_2');
|
||||
$route_match = new RouteMatch('test_route_2', $route, [], []);
|
||||
|
||||
// Asserts that the current user is passed to the access arguments resolver
|
||||
// factory.
|
||||
$this->setupAccessArgumentsResolverFactory()
|
||||
->with($route_match, $this->currentUser, NULL);
|
||||
|
||||
$this->assertTrue($this->accessManager->check($route_match));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for the conjunction test.
|
||||
*
|
||||
* @return array
|
||||
* An array of data for check conjunctions.
|
||||
*
|
||||
* @see \Drupal\Tests\Core\Access\AccessManagerTest::testCheckConjunctions()
|
||||
*/
|
||||
public function providerTestCheckConjunctions() {
|
||||
$access_allow = AccessResult::allowed();
|
||||
$access_deny = AccessResult::neutral();
|
||||
$access_kill = AccessResult::forbidden();
|
||||
|
||||
$access_configurations = array();
|
||||
$access_configurations[] = array(
|
||||
'name' => 'test_route_4',
|
||||
'condition_one' => 'TRUE',
|
||||
'condition_two' => 'FALSE',
|
||||
'expected' => $access_kill,
|
||||
);
|
||||
$access_configurations[] = array(
|
||||
'name' => 'test_route_5',
|
||||
'condition_one' => 'TRUE',
|
||||
'condition_two' => 'NULL',
|
||||
'expected' => $access_deny,
|
||||
);
|
||||
$access_configurations[] = array(
|
||||
'name' => 'test_route_6',
|
||||
'condition_one' => 'FALSE',
|
||||
'condition_two' => 'NULL',
|
||||
'expected' => $access_kill,
|
||||
);
|
||||
$access_configurations[] = array(
|
||||
'name' => 'test_route_7',
|
||||
'condition_one' => 'TRUE',
|
||||
'condition_two' => 'TRUE',
|
||||
'expected' => $access_allow,
|
||||
);
|
||||
$access_configurations[] = array(
|
||||
'name' => 'test_route_8',
|
||||
'condition_one' => 'FALSE',
|
||||
'condition_two' => 'FALSE',
|
||||
'expected' => $access_kill,
|
||||
);
|
||||
$access_configurations[] = array(
|
||||
'name' => 'test_route_9',
|
||||
'condition_one' => 'NULL',
|
||||
'condition_two' => 'NULL',
|
||||
'expected' => $access_deny,
|
||||
);
|
||||
|
||||
return $access_configurations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test \Drupal\Core\Access\AccessManager::check() with conjunctions.
|
||||
*
|
||||
* @dataProvider providerTestCheckConjunctions
|
||||
*/
|
||||
public function testCheckConjunctions($name, $condition_one, $condition_two, $expected_access) {
|
||||
$this->setupAccessChecker();
|
||||
$access_check = new DefinedTestAccessCheck();
|
||||
$this->container->register('test_access_defined', $access_check);
|
||||
$this->checkProvider->addCheckService('test_access_defined', 'access', array('_test_access'));
|
||||
|
||||
$route_collection = new RouteCollection();
|
||||
// Setup a test route for each access configuration.
|
||||
$requirements = array(
|
||||
'_access' => $condition_one,
|
||||
'_test_access' => $condition_two,
|
||||
);
|
||||
$route = new Route($name, array(), $requirements);
|
||||
$route_collection->add($name, $route);
|
||||
|
||||
$this->checkProvider->setChecks($route_collection);
|
||||
$this->setupAccessArgumentsResolverFactory();
|
||||
|
||||
$route_match = new RouteMatch($name, $route, array(), array());
|
||||
$this->assertEquals($expected_access->isAllowed(), $this->accessManager->check($route_match, $this->account));
|
||||
$this->assertEquals($expected_access, $this->accessManager->check($route_match, $this->account, NULL, TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the checkNamedRoute method.
|
||||
*
|
||||
* @see \Drupal\Core\Access\AccessManager::checkNamedRoute()
|
||||
*/
|
||||
public function testCheckNamedRoute() {
|
||||
$this->setupAccessChecker();
|
||||
$this->checkProvider->setChecks($this->routeCollection);
|
||||
$this->setupAccessArgumentsResolverFactory();
|
||||
|
||||
$this->paramConverter->expects($this->at(0))
|
||||
->method('convert')
|
||||
->with(array(RouteObjectInterface::ROUTE_NAME => 'test_route_2', RouteObjectInterface::ROUTE_OBJECT => $this->routeCollection->get('test_route_2')))
|
||||
->will($this->returnValue(array()));
|
||||
$this->paramConverter->expects($this->at(1))
|
||||
->method('convert')
|
||||
->with(array(RouteObjectInterface::ROUTE_NAME => 'test_route_2', RouteObjectInterface::ROUTE_OBJECT => $this->routeCollection->get('test_route_2')))
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$this->paramConverter->expects($this->at(2))
|
||||
->method('convert')
|
||||
->with(array('value' => 'example', RouteObjectInterface::ROUTE_NAME => 'test_route_4', RouteObjectInterface::ROUTE_OBJECT => $this->routeCollection->get('test_route_4')))
|
||||
->will($this->returnValue(array('value' => 'example')));
|
||||
$this->paramConverter->expects($this->at(3))
|
||||
->method('convert')
|
||||
->with(array('value' => 'example', RouteObjectInterface::ROUTE_NAME => 'test_route_4', RouteObjectInterface::ROUTE_OBJECT => $this->routeCollection->get('test_route_4')))
|
||||
->will($this->returnValue(array('value' => 'example')));
|
||||
|
||||
// Tests the access with routes with parameters without given request.
|
||||
$this->assertEquals(TRUE, $this->accessManager->checkNamedRoute('test_route_2', array(), $this->account));
|
||||
$this->assertEquals(AccessResult::allowed(), $this->accessManager->checkNamedRoute('test_route_2', array(), $this->account, TRUE));
|
||||
$this->assertEquals(TRUE, $this->accessManager->checkNamedRoute('test_route_4', array('value' => 'example'), $this->account));
|
||||
$this->assertEquals(AccessResult::allowed(), $this->accessManager->checkNamedRoute('test_route_4', array('value' => 'example'), $this->account, TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the checkNamedRoute with upcasted values.
|
||||
*
|
||||
* @see \Drupal\Core\Access\AccessManager::checkNamedRoute()
|
||||
*/
|
||||
public function testCheckNamedRouteWithUpcastedValues() {
|
||||
$this->routeCollection = new RouteCollection();
|
||||
$route = new Route('/test-route-1/{value}', array(), array('_test_access' => 'TRUE'));
|
||||
$this->routeCollection->add('test_route_1', $route);
|
||||
|
||||
$this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
|
||||
$this->routeProvider->expects($this->any())
|
||||
->method('getRouteByName')
|
||||
->with('test_route_1', array('value' => 'example'))
|
||||
->will($this->returnValue($route));
|
||||
|
||||
$map = array();
|
||||
$map[] = array('test_route_1', array('value' => 'example'), '/test-route-1/example');
|
||||
|
||||
$this->paramConverter = $this->getMock('Drupal\Core\ParamConverter\ParamConverterManagerInterface');
|
||||
$this->paramConverter->expects($this->atLeastOnce())
|
||||
->method('convert')
|
||||
->with(array('value' => 'example', RouteObjectInterface::ROUTE_NAME => 'test_route_1', RouteObjectInterface::ROUTE_OBJECT => $route))
|
||||
->will($this->returnValue(array('value' => 'upcasted_value')));
|
||||
|
||||
$this->setupAccessArgumentsResolverFactory($this->exactly(2))
|
||||
->with($this->callback(function ($route_match) {
|
||||
return $route_match->getParameters()->get('value') == 'upcasted_value';
|
||||
}));
|
||||
|
||||
$this->accessManager = new AccessManager($this->routeProvider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider);
|
||||
|
||||
$access_check = $this->getMock('Drupal\Tests\Core\Access\TestAccessCheckInterface');
|
||||
$access_check->expects($this->atLeastOnce())
|
||||
->method('applies')
|
||||
->will($this->returnValue(TRUE));
|
||||
$access_check->expects($this->atLeastOnce())
|
||||
->method('access')
|
||||
->will($this->returnValue(AccessResult::forbidden()));
|
||||
|
||||
$this->container->set('test_access', $access_check);
|
||||
|
||||
$this->checkProvider->addCheckService('test_access', 'access');
|
||||
$this->checkProvider->setChecks($this->routeCollection);
|
||||
|
||||
$this->assertEquals(FALSE, $this->accessManager->checkNamedRoute('test_route_1', array('value' => 'example'), $this->account));
|
||||
$this->assertEquals(AccessResult::forbidden(), $this->accessManager->checkNamedRoute('test_route_1', array('value' => 'example'), $this->account, TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the checkNamedRoute with default values.
|
||||
*
|
||||
* @covers ::checkNamedRoute
|
||||
*/
|
||||
public function testCheckNamedRouteWithDefaultValue() {
|
||||
$this->routeCollection = new RouteCollection();
|
||||
$route = new Route('/test-route-1/{value}', array('value' => 'example'), array('_test_access' => 'TRUE'));
|
||||
$this->routeCollection->add('test_route_1', $route);
|
||||
|
||||
$this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
|
||||
$this->routeProvider->expects($this->any())
|
||||
->method('getRouteByName')
|
||||
->with('test_route_1', array())
|
||||
->will($this->returnValue($route));
|
||||
|
||||
$map = array();
|
||||
$map[] = array('test_route_1', array('value' => 'example'), '/test-route-1/example');
|
||||
|
||||
$this->paramConverter = $this->getMock('Drupal\Core\ParamConverter\ParamConverterManagerInterface');
|
||||
$this->paramConverter->expects($this->atLeastOnce())
|
||||
->method('convert')
|
||||
->with(array('value' => 'example', RouteObjectInterface::ROUTE_NAME => 'test_route_1', RouteObjectInterface::ROUTE_OBJECT => $route))
|
||||
->will($this->returnValue(array('value' => 'upcasted_value')));
|
||||
|
||||
$this->setupAccessArgumentsResolverFactory($this->exactly(2))
|
||||
->with($this->callback(function ($route_match) {
|
||||
return $route_match->getParameters()->get('value') == 'upcasted_value';
|
||||
}));
|
||||
|
||||
$this->accessManager = new AccessManager($this->routeProvider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider);
|
||||
|
||||
$access_check = $this->getMock('Drupal\Tests\Core\Access\TestAccessCheckInterface');
|
||||
$access_check->expects($this->atLeastOnce())
|
||||
->method('applies')
|
||||
->will($this->returnValue(TRUE));
|
||||
$access_check->expects($this->atLeastOnce())
|
||||
->method('access')
|
||||
->will($this->returnValue(AccessResult::forbidden()));
|
||||
|
||||
$this->container->set('test_access', $access_check);
|
||||
|
||||
$this->checkProvider->addCheckService('test_access', 'access');
|
||||
$this->checkProvider->setChecks($this->routeCollection);
|
||||
|
||||
$this->assertEquals(FALSE, $this->accessManager->checkNamedRoute('test_route_1', array(), $this->account));
|
||||
$this->assertEquals(AccessResult::forbidden(), $this->accessManager->checkNamedRoute('test_route_1', array(), $this->account, TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests checkNamedRoute given an invalid/non existing route name.
|
||||
*/
|
||||
public function testCheckNamedRouteWithNonExistingRoute() {
|
||||
$this->routeProvider->expects($this->any())
|
||||
->method('getRouteByName')
|
||||
->will($this->throwException(new RouteNotFoundException()));
|
||||
|
||||
$this->setupAccessChecker();
|
||||
|
||||
$this->assertEquals(FALSE, $this->accessManager->checkNamedRoute('test_route_1', array(), $this->account), 'A non existing route lead to access.');
|
||||
$this->assertEquals(AccessResult::forbidden()->addCacheTags(['config:core.extension']), $this->accessManager->checkNamedRoute('test_route_1', array(), $this->account, TRUE), 'A non existing route lead to access.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that an access checker throws an exception for not allowed values.
|
||||
*
|
||||
* @dataProvider providerCheckException
|
||||
*
|
||||
* @expectedException \Drupal\Core\Access\AccessException
|
||||
*/
|
||||
public function testCheckException($return_value) {
|
||||
$route_provider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
|
||||
|
||||
// Setup a test route for each access configuration.
|
||||
$requirements = array(
|
||||
'_test_incorrect_value' => 'TRUE',
|
||||
);
|
||||
$options = array(
|
||||
'_access_checks' => array(
|
||||
'test_incorrect_value',
|
||||
),
|
||||
);
|
||||
$route = new Route('', array(), $requirements, $options);
|
||||
|
||||
$route_provider->expects($this->any())
|
||||
->method('getRouteByName')
|
||||
->will($this->returnValue($route));
|
||||
|
||||
$this->paramConverter = $this->getMock('Drupal\Core\ParamConverter\ParamConverterManagerInterface');
|
||||
$this->paramConverter->expects($this->any())
|
||||
->method('convert')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$this->setupAccessArgumentsResolverFactory();
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
|
||||
// Register a service that will return an incorrect value.
|
||||
$access_check = $this->getMock('Drupal\Tests\Core\Access\TestAccessCheckInterface');
|
||||
$access_check->expects($this->any())
|
||||
->method('access')
|
||||
->will($this->returnValue($return_value));
|
||||
$container->set('test_incorrect_value', $access_check);
|
||||
|
||||
$access_manager = new AccessManager($route_provider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider);
|
||||
$this->checkProvider->setContainer($container);
|
||||
$this->checkProvider->addCheckService('test_incorrect_value', 'access');
|
||||
|
||||
$access_manager->checkNamedRoute('test_incorrect_value', array(), $this->account);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testCheckException.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerCheckException() {
|
||||
return array(
|
||||
array(array(1)),
|
||||
array('string'),
|
||||
array(0),
|
||||
array(1),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a default access check service to the container and the access manager.
|
||||
*/
|
||||
protected function setupAccessChecker() {
|
||||
$access_check = new DefaultAccessCheck();
|
||||
$this->container->register('test_access_default', $access_check);
|
||||
$this->checkProvider->addCheckService('test_access_default', 'access', array('_access'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add default expectations to the access arguments resolver factory.
|
||||
*/
|
||||
protected function setupAccessArgumentsResolverFactory($constraint = NULL) {
|
||||
if (!isset($constraint)) {
|
||||
$constraint = $this->any();
|
||||
}
|
||||
return $this->argumentsResolverFactory->expects($constraint)
|
||||
->method('getArgumentsResolver')
|
||||
->will($this->returnCallback(function ($route_match, $account) {
|
||||
$resolver = $this->getMock('Drupal\Component\Utility\ArgumentsResolverInterface');
|
||||
$resolver->expects($this->any())
|
||||
->method('getArguments')
|
||||
->will($this->returnCallback(function ($callable) use ($route_match) {
|
||||
return array($route_match->getRouteObject());
|
||||
}));
|
||||
return $resolver;
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines an interface with a defined access() method for mocking.
|
||||
*/
|
||||
interface TestAccessCheckInterface extends AccessCheckInterface {
|
||||
public function access();
|
||||
}
|
938
core/tests/Drupal/Tests/Core/Access/AccessResultTest.php
Normal file
938
core/tests/Drupal/Tests/Core/Access/AccessResultTest.php
Normal file
|
@ -0,0 +1,938 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Access\AccessResultTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Access\AccessResultInterface;
|
||||
use Drupal\Core\Access\AccessResultNeutral;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheableDependencyInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Access\AccessResult
|
||||
* @group Access
|
||||
*/
|
||||
class AccessResultTest extends UnitTestCase {
|
||||
|
||||
protected function assertDefaultCacheability(AccessResult $access) {
|
||||
$this->assertSame([], $access->getCacheContexts());
|
||||
$this->assertSame([], $access->getCacheTags());
|
||||
$this->assertSame(Cache::PERMANENT, $access->getCacheMaxAge());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the construction of an AccessResult object.
|
||||
*
|
||||
* @covers ::__construct
|
||||
* @covers ::neutral
|
||||
*/
|
||||
public function testConstruction() {
|
||||
$verify = function (AccessResult $access) {
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertTrue($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
};
|
||||
|
||||
// Verify the object when using the constructor.
|
||||
$a = new AccessResultNeutral();
|
||||
$verify($a);
|
||||
|
||||
// Verify the object when using the ::create() convenience method.
|
||||
$b = AccessResult::neutral();
|
||||
$verify($b);
|
||||
|
||||
$this->assertEquals($a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::allowed
|
||||
* @covers ::isAllowed
|
||||
* @covers ::isForbidden
|
||||
* @covers ::isNeutral
|
||||
*/
|
||||
public function testAccessAllowed() {
|
||||
$verify = function (AccessResult $access) {
|
||||
$this->assertTrue($access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
};
|
||||
|
||||
// Verify the object when using the ::allowed() convenience static method.
|
||||
$b = AccessResult::allowed();
|
||||
$verify($b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::forbidden
|
||||
* @covers ::isAllowed
|
||||
* @covers ::isForbidden
|
||||
* @covers ::isNeutral
|
||||
*/
|
||||
public function testAccessForbidden() {
|
||||
$verify = function (AccessResult $access) {
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
};
|
||||
|
||||
// Verify the object when using the ::forbidden() convenience static method.
|
||||
$b = AccessResult::forbidden();
|
||||
$verify($b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::allowedIf
|
||||
* @covers ::isAllowed
|
||||
* @covers ::isForbidden
|
||||
* @covers ::isNeutral
|
||||
*/
|
||||
public function testAccessConditionallyAllowed() {
|
||||
$verify = function (AccessResult $access, $allowed) {
|
||||
$this->assertSame($allowed, $access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertSame(!$allowed, $access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
};
|
||||
|
||||
$b1 = AccessResult::allowedIf(TRUE);
|
||||
$verify($b1, TRUE);
|
||||
$b2 = AccessResult::allowedIf(FALSE);
|
||||
$verify($b2, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::forbiddenIf
|
||||
* @covers ::isAllowed
|
||||
* @covers ::isForbidden
|
||||
* @covers ::isNeutral
|
||||
*/
|
||||
public function testAccessConditionallyForbidden() {
|
||||
$verify = function (AccessResult $access, $forbidden) {
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertSame($forbidden, $access->isForbidden());
|
||||
$this->assertSame(!$forbidden, $access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
};
|
||||
|
||||
$b1 = AccessResult::forbiddenIf(TRUE);
|
||||
$verify($b1, TRUE);
|
||||
$b2 = AccessResult::forbiddenIf(FALSE);
|
||||
$verify($b2, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::andIf
|
||||
*/
|
||||
public function testAndIf() {
|
||||
$neutral = AccessResult::neutral();
|
||||
$allowed = AccessResult::allowed();
|
||||
$forbidden = AccessResult::forbidden();
|
||||
$unused_access_result_due_to_lazy_evaluation = $this->getMock('\Drupal\Core\Access\AccessResultInterface');
|
||||
$unused_access_result_due_to_lazy_evaluation->expects($this->never())
|
||||
->method($this->anything());
|
||||
|
||||
// ALLOWED && ALLOWED === ALLOWED.
|
||||
$access = $allowed->andIf($allowed);
|
||||
$this->assertTrue($access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// ALLOWED && NEUTRAL === NEUTRAL.
|
||||
$access = $allowed->andIf($neutral);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertTrue($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// ALLOWED && FORBIDDEN === FORBIDDEN.
|
||||
$access = $allowed->andIf($forbidden);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// NEUTRAL && ALLOW == NEUTRAL
|
||||
$access = $neutral->andIf($allowed);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertTrue($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// NEUTRAL && NEUTRAL === NEUTRAL.
|
||||
$access = $neutral->andIf($neutral);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertTrue($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// NEUTRAL && FORBIDDEN === FORBIDDEN.
|
||||
$access = $neutral->andIf($forbidden);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// FORBIDDEN && ALLOWED = FORBIDDEN
|
||||
$access = $forbidden->andif($allowed);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// FORBIDDEN && NEUTRAL = FORBIDDEN
|
||||
$access = $forbidden->andif($neutral);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// FORBIDDEN && FORBIDDEN = FORBIDDEN
|
||||
$access = $forbidden->andif($forbidden);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// FORBIDDEN && * === FORBIDDEN: lazy evaluation verification.
|
||||
$access = $forbidden->andIf($unused_access_result_due_to_lazy_evaluation);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::orIf
|
||||
*/
|
||||
public function testOrIf() {
|
||||
$neutral = AccessResult::neutral();
|
||||
$allowed = AccessResult::allowed();
|
||||
$forbidden = AccessResult::forbidden();
|
||||
$unused_access_result_due_to_lazy_evaluation = $this->getMock('\Drupal\Core\Access\AccessResultInterface');
|
||||
$unused_access_result_due_to_lazy_evaluation->expects($this->never())
|
||||
->method($this->anything());
|
||||
|
||||
// ALLOWED || ALLOWED === ALLOWED.
|
||||
$access = $allowed->orIf($allowed);
|
||||
$this->assertTrue($access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// ALLOWED || NEUTRAL === ALLOWED.
|
||||
$access = $allowed->orIf($neutral);
|
||||
$this->assertTrue($access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// ALLOWED || FORBIDDEN === FORBIDDEN.
|
||||
$access = $allowed->orIf($forbidden);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// NEUTRAL || NEUTRAL === NEUTRAL.
|
||||
$access = $neutral->orIf($neutral);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertTrue($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// NEUTRAL || ALLOWED === ALLOWED.
|
||||
$access = $neutral->orIf($allowed);
|
||||
$this->assertTrue($access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// NEUTRAL || FORBIDDEN === FORBIDDEN.
|
||||
$access = $neutral->orIf($forbidden);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// FORBIDDEN || ALLOWED === FORBIDDEN.
|
||||
$access = $forbidden->orIf($allowed);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// FORBIDDEN || NEUTRAL === FORBIDDEN.
|
||||
$access = $forbidden->orIf($allowed);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// FORBIDDEN || FORBIDDEN === FORBIDDEN.
|
||||
$access = $forbidden->orIf($allowed);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
|
||||
// FORBIDDEN || * === FORBIDDEN.
|
||||
$access = $forbidden->orIf($unused_access_result_due_to_lazy_evaluation);
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertTrue($access->isForbidden());
|
||||
$this->assertFalse($access->isNeutral());
|
||||
$this->assertDefaultCacheability($access);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setCacheMaxAge
|
||||
* @covers ::getCacheMaxAge
|
||||
*/
|
||||
public function testCacheMaxAge() {
|
||||
$this->assertSame(Cache::PERMANENT, AccessResult::neutral()->getCacheMaxAge());
|
||||
$this->assertSame(1337, AccessResult::neutral()->setCacheMaxAge(1337)->getCacheMaxAge());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::addCacheContexts
|
||||
* @covers ::resetCacheContexts
|
||||
* @covers ::getCacheContexts
|
||||
* @covers ::cachePerPermissions
|
||||
* @covers ::cachePerUser
|
||||
* @covers ::allowedIfHasPermission
|
||||
*/
|
||||
public function testCacheContexts() {
|
||||
$verify = function (AccessResult $access, array $contexts) {
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertTrue($access->isNeutral());
|
||||
$this->assertSame(Cache::PERMANENT, $access->getCacheMaxAge());
|
||||
$this->assertSame($contexts, $access->getCacheContexts());
|
||||
$this->assertSame([], $access->getCacheTags());
|
||||
};
|
||||
|
||||
$access = AccessResult::neutral()->addCacheContexts(['foo']);
|
||||
$verify($access, ['foo']);
|
||||
// Verify resetting works.
|
||||
$access->resetCacheContexts();
|
||||
$verify($access, []);
|
||||
// Verify idempotency.
|
||||
$access->addCacheContexts(['foo'])
|
||||
->addCacheContexts(['foo']);
|
||||
$verify($access, ['foo']);
|
||||
// Verify same values in different call order yields the same result.
|
||||
$access->resetCacheContexts()
|
||||
->addCacheContexts(['foo'])
|
||||
->addCacheContexts(['bar']);
|
||||
$verify($access, ['bar', 'foo']);
|
||||
$access->resetCacheContexts()
|
||||
->addCacheContexts(['bar'])
|
||||
->addCacheContexts(['foo']);
|
||||
$verify($access, ['bar', 'foo']);
|
||||
|
||||
// ::cachePerPermissions() convenience method.
|
||||
$contexts = array('user.permissions');
|
||||
$a = AccessResult::neutral()->addCacheContexts($contexts);
|
||||
$verify($a, $contexts);
|
||||
$b = AccessResult::neutral()->cachePerPermissions();
|
||||
$verify($b, $contexts);
|
||||
$this->assertEquals($a, $b);
|
||||
|
||||
// ::cachePerUser() convenience method.
|
||||
$contexts = array('user');
|
||||
$a = AccessResult::neutral()->addCacheContexts($contexts);
|
||||
$verify($a, $contexts);
|
||||
$b = AccessResult::neutral()->cachePerUser();
|
||||
$verify($b, $contexts);
|
||||
$this->assertEquals($a, $b);
|
||||
|
||||
// Both.
|
||||
$contexts = array('user', 'user.permissions');
|
||||
$a = AccessResult::neutral()->addCacheContexts($contexts);
|
||||
$verify($a, $contexts);
|
||||
$b = AccessResult::neutral()->cachePerPermissions()->cachePerUser();
|
||||
$verify($b, $contexts);
|
||||
$c = AccessResult::neutral()->cachePerUser()->cachePerPermissions();
|
||||
$verify($c, $contexts);
|
||||
$this->assertEquals($a, $b);
|
||||
$this->assertEquals($a, $c);
|
||||
|
||||
// ::allowIfHasPermission and ::allowedIfHasPermission convenience methods.
|
||||
$account = $this->getMock('\Drupal\Core\Session\AccountInterface');
|
||||
$account->expects($this->any())
|
||||
->method('hasPermission')
|
||||
->with('may herd llamas')
|
||||
->will($this->returnValue(FALSE));
|
||||
$contexts = array('user.permissions');
|
||||
|
||||
// Verify the object when using the ::allowedIfHasPermission() convenience
|
||||
// static method.
|
||||
$b = AccessResult::allowedIfHasPermission($account, 'may herd llamas');
|
||||
$verify($b, $contexts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::addCacheTags
|
||||
* @covers ::resetCacheTags
|
||||
* @covers ::getCacheTags
|
||||
* @covers ::cacheUntilEntityChanges
|
||||
* @covers ::cacheUntilConfigurationChanges
|
||||
*/
|
||||
public function testCacheTags() {
|
||||
$verify = function (AccessResult $access, array $tags) {
|
||||
$this->assertFalse($access->isAllowed());
|
||||
$this->assertFalse($access->isForbidden());
|
||||
$this->assertTrue($access->isNeutral());
|
||||
$this->assertSame(Cache::PERMANENT, $access->getCacheMaxAge());
|
||||
$this->assertSame([], $access->getCacheContexts());
|
||||
$this->assertSame($tags, $access->getCacheTags());
|
||||
};
|
||||
|
||||
$access = AccessResult::neutral()->addCacheTags(['foo:bar']);
|
||||
$verify($access, ['foo:bar']);
|
||||
// Verify resetting works.
|
||||
$access->resetCacheTags();
|
||||
$verify($access, []);
|
||||
// Verify idempotency.
|
||||
$access->addCacheTags(['foo:bar'])
|
||||
->addCacheTags(['foo:bar']);
|
||||
$verify($access, ['foo:bar']);
|
||||
// Verify same values in different call order yields the same result.
|
||||
$access->resetCacheTags()
|
||||
->addCacheTags(['bar:baz'])
|
||||
->addCacheTags(['bar:qux'])
|
||||
->addCacheTags(['foo:bar'])
|
||||
->addCacheTags(['foo:baz']);
|
||||
$verify($access, ['bar:baz', 'bar:qux', 'foo:bar', 'foo:baz']);
|
||||
$access->resetCacheTags()
|
||||
->addCacheTags(['foo:bar'])
|
||||
->addCacheTags(['bar:qux'])
|
||||
->addCacheTags(['foo:baz'])
|
||||
->addCacheTags(['bar:baz']);
|
||||
$verify($access, ['bar:baz', 'bar:qux', 'foo:bar', 'foo:baz']);
|
||||
|
||||
// ::cacheUntilEntityChanges() convenience method.
|
||||
$node = $this->getMock('\Drupal\node\NodeInterface');
|
||||
$node->expects($this->any())
|
||||
->method('getCacheTags')
|
||||
->will($this->returnValue(array('node:20011988')));
|
||||
$tags = array('node:20011988');
|
||||
$a = AccessResult::neutral()->addCacheTags($tags);
|
||||
$verify($a, $tags);
|
||||
$b = AccessResult::neutral()->cacheUntilEntityChanges($node);
|
||||
$verify($b, $tags);
|
||||
$this->assertEquals($a, $b);
|
||||
|
||||
// ::cacheUntilConfigurationChanges() convenience method.
|
||||
$configuration = $this->getMock('\Drupal\Core\Config\ConfigBase');
|
||||
$configuration->expects($this->any())
|
||||
->method('getCacheTags')
|
||||
->will($this->returnValue(array('config:foo.bar.baz')));
|
||||
$tags = array('config:foo.bar.baz');
|
||||
$a = AccessResult::neutral()->addCacheTags($tags);
|
||||
$verify($a, $tags);
|
||||
$b = AccessResult::neutral()->cacheUntilConfigurationChanges($configuration);
|
||||
$verify($b, $tags);
|
||||
$this->assertEquals($a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::inheritCacheability
|
||||
*/
|
||||
public function testInheritCacheability() {
|
||||
// andIf(); 1st has defaults, 2nd has custom tags, contexts and max-age.
|
||||
$access = AccessResult::allowed();
|
||||
$other = AccessResult::allowed()->setCacheMaxAge(1500)->cachePerPermissions()->addCacheTags(['node:20011988']);
|
||||
$this->assertTrue($access->inheritCacheability($other) instanceof AccessResult);
|
||||
$this->assertSame(['user.permissions'], $access->getCacheContexts());
|
||||
$this->assertSame(['node:20011988'], $access->getCacheTags());
|
||||
$this->assertSame(1500, $access->getCacheMaxAge());
|
||||
|
||||
// andIf(); 1st has custom tags, max-age, 2nd has custom contexts and max-age.
|
||||
$access = AccessResult::allowed()->cachePerUser()->setCacheMaxAge(43200);
|
||||
$other = AccessResult::forbidden()->addCacheTags(['node:14031991'])->setCacheMaxAge(86400);
|
||||
$this->assertTrue($access->inheritCacheability($other) instanceof AccessResult);
|
||||
$this->assertSame(['user'], $access->getCacheContexts());
|
||||
$this->assertSame(['node:14031991'], $access->getCacheTags());
|
||||
$this->assertSame(43200, $access->getCacheMaxAge());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of access result pairs and operations to test.
|
||||
*
|
||||
* This tests the propagation of cacheability metadata. Rather than testing
|
||||
* every single bit of cacheability metadata, which would lead to a mind-
|
||||
* boggling number of permutations, in this test, we only consider the
|
||||
* permutations of all pairs of the following set:
|
||||
* - Allowed, implements CDI and is cacheable.
|
||||
* - Allowed, implements CDI and is not cacheable.
|
||||
* - Allowed, does not implement CDI (hence not cacheable).
|
||||
* - Forbidden, implements CDI and is cacheable.
|
||||
* - Forbidden, implements CDI and is not cacheable.
|
||||
* - Forbidden, does not implement CDI (hence not cacheable).
|
||||
* - Neutral, implements CDI and is cacheable.
|
||||
* - Neutral, implements CDI and is not cacheable.
|
||||
* - Neutral, does not implement CDI (hence not cacheable).
|
||||
*
|
||||
* (Where "CDI" is CacheableDependencyInterface.)
|
||||
*
|
||||
* This leads to 72 permutations (9!/(9-2)! = 9*8 = 72) per operation. There
|
||||
* are two operations to test (AND and OR), so that leads to a grand total of
|
||||
* 144 permutations, all of which are tested.
|
||||
*
|
||||
* There are two "contagious" patterns:
|
||||
* - Any operation with a forbidden access result yields a forbidden result.
|
||||
* This therefore also applies to the cacheability metadata associated with
|
||||
* a forbidden result. This is the case for bullets 4, 5 and 6 in the set
|
||||
* above.
|
||||
* - Any operation yields an access result object that is of the same class
|
||||
* (implementation) as the first operand. This is because operations are
|
||||
* invoked on the first operand. Therefore, if the first implementation
|
||||
* does not implement CacheableDependencyInterface, then the result won't
|
||||
* either. This is the case for bullets 3, 6 and 9 in the set above.
|
||||
*/
|
||||
public function andOrCacheabilityPropagationProvider() {
|
||||
// ct: cacheable=true, cf: cacheable=false, un: uncacheable.
|
||||
// Note: the test cases that have a "un" access result as the first operand
|
||||
// test UncacheableTestAccessResult, not AccessResult. However, we
|
||||
// definitely want to verify that AccessResult's orIf() and andIf() methods
|
||||
// work correctly when given an AccessResultInterface implementation that
|
||||
// does not implement CacheableDependencyInterface, and we want to test the
|
||||
// full gamut of permutations, so that's not a problem.
|
||||
$allowed_ct = AccessResult::allowed();
|
||||
$allowed_cf = AccessResult::allowed()->setCacheMaxAge(0);
|
||||
$allowed_un = new UncacheableTestAccessResult('ALLOWED');
|
||||
$forbidden_ct = AccessResult::forbidden();
|
||||
$forbidden_cf = AccessResult::forbidden()->setCacheMaxAge(0);
|
||||
$forbidden_un = new UncacheableTestAccessResult('FORBIDDEN');
|
||||
$neutral_ct = AccessResult::neutral();
|
||||
$neutral_cf = AccessResult::neutral()->setCacheMaxAge(0);
|
||||
$neutral_un = new UncacheableTestAccessResult('NEUTRAL');
|
||||
|
||||
// Structure:
|
||||
// - First column: first access result.
|
||||
// - Second column: operator ('OR' or 'AND').
|
||||
// - Third column: second access result.
|
||||
// - Fourth column: whether result implements CacheableDependencyInterface
|
||||
// - Fifth column: whether the result is cacheable (if column 4 is TRUE)
|
||||
return [
|
||||
// Allowed (ct) OR allowed (ct,cf,un).
|
||||
[$allowed_ct, 'OR', $allowed_ct, TRUE, TRUE],
|
||||
[$allowed_ct, 'OR', $allowed_cf, TRUE, TRUE],
|
||||
[$allowed_ct, 'OR', $allowed_un, TRUE, TRUE],
|
||||
// Allowed (cf) OR allowed (ct,cf,un).
|
||||
[$allowed_cf, 'OR', $allowed_ct, TRUE, TRUE],
|
||||
[$allowed_cf, 'OR', $allowed_cf, TRUE, FALSE],
|
||||
[$allowed_cf, 'OR', $allowed_un, TRUE, FALSE],
|
||||
// Allowed (un) OR allowed (ct,cf,un).
|
||||
[$allowed_un, 'OR', $allowed_ct, FALSE, NULL],
|
||||
[$allowed_un, 'OR', $allowed_cf, FALSE, NULL],
|
||||
[$allowed_un, 'OR', $allowed_un, FALSE, NULL],
|
||||
|
||||
// Allowed (ct) OR forbidden (ct,cf,un).
|
||||
[$allowed_ct, 'OR', $forbidden_ct, TRUE, TRUE],
|
||||
[$allowed_ct, 'OR', $forbidden_cf, TRUE, FALSE],
|
||||
[$allowed_ct, 'OR', $forbidden_un, TRUE, FALSE],
|
||||
// Allowed (cf) OR forbidden (ct,cf,un).
|
||||
[$allowed_cf, 'OR', $forbidden_ct, TRUE, TRUE],
|
||||
[$allowed_cf, 'OR', $forbidden_cf, TRUE, FALSE],
|
||||
[$allowed_cf, 'OR', $forbidden_un, TRUE, FALSE],
|
||||
// Allowed (un) OR forbidden (ct,cf,un).
|
||||
[$allowed_un, 'OR', $forbidden_ct, FALSE, NULL],
|
||||
[$allowed_un, 'OR', $forbidden_cf, FALSE, NULL],
|
||||
[$allowed_un, 'OR', $forbidden_un, FALSE, NULL],
|
||||
|
||||
// Allowed (ct) OR neutral (ct,cf,un).
|
||||
[$allowed_ct, 'OR', $neutral_ct, TRUE, TRUE],
|
||||
[$allowed_ct, 'OR', $neutral_cf, TRUE, TRUE],
|
||||
[$allowed_ct, 'OR', $neutral_un, TRUE, TRUE],
|
||||
// Allowed (cf) OR neutral (ct,cf,un).
|
||||
[$allowed_cf, 'OR', $neutral_ct, TRUE, FALSE],
|
||||
[$allowed_cf, 'OR', $neutral_cf, TRUE, FALSE],
|
||||
[$allowed_cf, 'OR', $neutral_un, TRUE, FALSE],
|
||||
// Allowed (un) OR neutral (ct,cf,un).
|
||||
[$allowed_un, 'OR', $neutral_ct, FALSE, NULL],
|
||||
[$allowed_un, 'OR', $neutral_cf, FALSE, NULL],
|
||||
[$allowed_un, 'OR', $neutral_un, FALSE, NULL],
|
||||
|
||||
|
||||
// Forbidden (ct) OR allowed (ct,cf,un).
|
||||
[$forbidden_ct, 'OR', $allowed_ct, TRUE, TRUE],
|
||||
[$forbidden_ct, 'OR', $allowed_cf, TRUE, TRUE],
|
||||
[$forbidden_ct, 'OR', $allowed_un, TRUE, TRUE],
|
||||
// Forbidden (cf) OR allowed (ct,cf,un).
|
||||
[$forbidden_cf, 'OR', $allowed_ct, TRUE, FALSE],
|
||||
[$forbidden_cf, 'OR', $allowed_cf, TRUE, FALSE],
|
||||
[$forbidden_cf, 'OR', $allowed_un, TRUE, FALSE],
|
||||
// Forbidden (un) OR allowed (ct,cf,un).
|
||||
[$forbidden_un, 'OR', $allowed_ct, FALSE, NULL],
|
||||
[$forbidden_un, 'OR', $allowed_cf, FALSE, NULL],
|
||||
[$forbidden_un, 'OR', $allowed_un, FALSE, NULL],
|
||||
|
||||
// Forbidden (ct) OR neutral (ct,cf,un).
|
||||
[$forbidden_ct, 'OR', $neutral_ct, TRUE, TRUE],
|
||||
[$forbidden_ct, 'OR', $neutral_cf, TRUE, TRUE],
|
||||
[$forbidden_ct, 'OR', $neutral_un, TRUE, TRUE],
|
||||
// Forbidden (cf) OR neutral (ct,cf,un).
|
||||
[$forbidden_cf, 'OR', $neutral_ct, TRUE, FALSE],
|
||||
[$forbidden_cf, 'OR', $neutral_cf, TRUE, FALSE],
|
||||
[$forbidden_cf, 'OR', $neutral_un, TRUE, FALSE],
|
||||
// Forbidden (un) OR neutral (ct,cf,un).
|
||||
[$forbidden_un, 'OR', $neutral_ct, FALSE, NULL],
|
||||
[$forbidden_un, 'OR', $neutral_cf, FALSE, NULL],
|
||||
[$forbidden_un, 'OR', $neutral_un, FALSE, NULL],
|
||||
|
||||
// Forbidden (ct) OR forbidden (ct,cf,un).
|
||||
[$forbidden_ct, 'OR', $forbidden_ct, TRUE, TRUE],
|
||||
[$forbidden_ct, 'OR', $forbidden_cf, TRUE, TRUE],
|
||||
[$forbidden_ct, 'OR', $forbidden_un, TRUE, TRUE],
|
||||
// Forbidden (cf) OR forbidden (ct,cf,un).
|
||||
[$forbidden_cf, 'OR', $forbidden_ct, TRUE, TRUE],
|
||||
[$forbidden_cf, 'OR', $forbidden_cf, TRUE, FALSE],
|
||||
[$forbidden_cf, 'OR', $forbidden_un, TRUE, FALSE],
|
||||
// Forbidden (un) OR forbidden (ct,cf,un).
|
||||
[$forbidden_un, 'OR', $forbidden_ct, FALSE, NULL],
|
||||
[$forbidden_un, 'OR', $forbidden_cf, FALSE, NULL],
|
||||
[$forbidden_un, 'OR', $forbidden_un, FALSE, NULL],
|
||||
|
||||
|
||||
// Neutral (ct) OR allowed (ct,cf,un).
|
||||
[$neutral_ct, 'OR', $allowed_ct, TRUE, TRUE],
|
||||
[$neutral_ct, 'OR', $allowed_cf, TRUE, FALSE],
|
||||
[$neutral_ct, 'OR', $allowed_un, TRUE, FALSE],
|
||||
// Neutral (cf) OR allowed (ct,cf,un).
|
||||
[$neutral_cf, 'OR', $allowed_ct, TRUE, TRUE],
|
||||
[$neutral_cf, 'OR', $allowed_cf, TRUE, FALSE],
|
||||
[$neutral_cf, 'OR', $allowed_un, TRUE, FALSE],
|
||||
// Neutral (un) OR allowed (ct,cf,un).
|
||||
[$neutral_un, 'OR', $allowed_ct, FALSE, NULL],
|
||||
[$neutral_un, 'OR', $allowed_cf, FALSE, NULL],
|
||||
[$neutral_un, 'OR', $allowed_un, FALSE, NULL],
|
||||
|
||||
// Neutral (ct) OR neutral (ct,cf,un).
|
||||
[$neutral_ct, 'OR', $neutral_ct, TRUE, TRUE],
|
||||
[$neutral_ct, 'OR', $neutral_cf, TRUE, TRUE],
|
||||
[$neutral_ct, 'OR', $neutral_un, TRUE, TRUE],
|
||||
// Neutral (cf) OR neutral (ct,cf,un).
|
||||
[$neutral_cf, 'OR', $neutral_ct, TRUE, TRUE],
|
||||
[$neutral_cf, 'OR', $neutral_cf, TRUE, FALSE],
|
||||
[$neutral_cf, 'OR', $neutral_un, TRUE, FALSE],
|
||||
// Neutral (un) OR neutral (ct,cf,un).
|
||||
[$neutral_un, 'OR', $neutral_ct, FALSE, NULL],
|
||||
[$neutral_un, 'OR', $neutral_cf, FALSE, NULL],
|
||||
[$neutral_un, 'OR', $neutral_un, FALSE, NULL],
|
||||
|
||||
// Neutral (ct) OR forbidden (ct,cf,un).
|
||||
[$neutral_ct, 'OR', $forbidden_ct, TRUE, TRUE],
|
||||
[$neutral_ct, 'OR', $forbidden_cf, TRUE, FALSE],
|
||||
[$neutral_ct, 'OR', $forbidden_un, TRUE, FALSE],
|
||||
// Neutral (cf) OR forbidden (ct,cf,un).
|
||||
[$neutral_cf, 'OR', $forbidden_ct, TRUE, TRUE],
|
||||
[$neutral_cf, 'OR', $forbidden_cf, TRUE, FALSE],
|
||||
[$neutral_cf, 'OR', $forbidden_un, TRUE, FALSE],
|
||||
// Neutral (un) OR forbidden (ct,cf,un).
|
||||
[$neutral_un, 'OR', $forbidden_ct, FALSE, NULL],
|
||||
[$neutral_un, 'OR', $forbidden_cf, FALSE, NULL],
|
||||
[$neutral_un, 'OR', $forbidden_un, FALSE, NULL],
|
||||
|
||||
|
||||
|
||||
|
||||
// Allowed (ct) AND allowed (ct,cf,un).
|
||||
[$allowed_ct, 'AND', $allowed_ct, TRUE, TRUE],
|
||||
[$allowed_ct, 'AND', $allowed_cf, TRUE, FALSE],
|
||||
[$allowed_ct, 'AND', $allowed_un, TRUE, FALSE],
|
||||
// Allowed (cf) AND allowed (ct,cf,un).
|
||||
[$allowed_cf, 'AND', $allowed_ct, TRUE, FALSE],
|
||||
[$allowed_cf, 'AND', $allowed_cf, TRUE, FALSE],
|
||||
[$allowed_cf, 'AND', $allowed_un, TRUE, FALSE],
|
||||
// Allowed (un) AND allowed (ct,cf,un).
|
||||
[$allowed_un, 'AND', $allowed_ct, FALSE, NULL],
|
||||
[$allowed_un, 'AND', $allowed_cf, FALSE, NULL],
|
||||
[$allowed_un, 'AND', $allowed_un, FALSE, NULL],
|
||||
|
||||
// Allowed (ct) AND forbidden (ct,cf,un).
|
||||
[$allowed_ct, 'AND', $forbidden_ct, TRUE, TRUE],
|
||||
[$allowed_ct, 'AND', $forbidden_cf, TRUE, FALSE],
|
||||
[$allowed_ct, 'AND', $forbidden_un, TRUE, FALSE],
|
||||
// Allowed (cf) AND forbidden (ct,cf,un).
|
||||
[$allowed_cf, 'AND', $forbidden_ct, TRUE, TRUE],
|
||||
[$allowed_cf, 'AND', $forbidden_cf, TRUE, FALSE],
|
||||
[$allowed_cf, 'AND', $forbidden_un, TRUE, FALSE],
|
||||
// Allowed (un) AND forbidden (ct,cf,un).
|
||||
[$allowed_un, 'AND', $forbidden_ct, FALSE, NULL],
|
||||
[$allowed_un, 'AND', $forbidden_cf, FALSE, NULL],
|
||||
[$allowed_un, 'AND', $forbidden_un, FALSE, NULL],
|
||||
|
||||
// Allowed (ct) AND neutral (ct,cf,un).
|
||||
[$allowed_ct, 'AND', $neutral_ct, TRUE, TRUE],
|
||||
[$allowed_ct, 'AND', $neutral_cf, TRUE, FALSE],
|
||||
[$allowed_ct, 'AND', $neutral_un, TRUE, FALSE],
|
||||
// Allowed (cf) AND neutral (ct,cf,un).
|
||||
[$allowed_cf, 'AND', $neutral_ct, TRUE, FALSE],
|
||||
[$allowed_cf, 'AND', $neutral_cf, TRUE, FALSE],
|
||||
[$allowed_cf, 'AND', $neutral_un, TRUE, FALSE],
|
||||
// Allowed (un) AND neutral (ct,cf,un).
|
||||
[$allowed_un, 'AND', $neutral_ct, FALSE, NULL],
|
||||
[$allowed_un, 'AND', $neutral_cf, FALSE, NULL],
|
||||
[$allowed_un, 'AND', $neutral_un, FALSE, NULL],
|
||||
|
||||
|
||||
// Forbidden (ct) AND allowed (ct,cf,un).
|
||||
[$forbidden_ct, 'AND', $allowed_ct, TRUE, TRUE],
|
||||
[$forbidden_ct, 'AND', $allowed_cf, TRUE, TRUE],
|
||||
[$forbidden_ct, 'AND', $allowed_un, TRUE, TRUE],
|
||||
// Forbidden (cf) AND allowed (ct,cf,un).
|
||||
[$forbidden_cf, 'AND', $allowed_ct, TRUE, FALSE],
|
||||
[$forbidden_cf, 'AND', $allowed_cf, TRUE, FALSE],
|
||||
[$forbidden_cf, 'AND', $allowed_un, TRUE, FALSE],
|
||||
// Forbidden (un) AND allowed (ct,cf,un).
|
||||
[$forbidden_un, 'AND', $allowed_ct, FALSE, NULL],
|
||||
[$forbidden_un, 'AND', $allowed_cf, FALSE, NULL],
|
||||
[$forbidden_un, 'AND', $allowed_un, FALSE, NULL],
|
||||
|
||||
// Forbidden (ct) AND neutral (ct,cf,un).
|
||||
[$forbidden_ct, 'AND', $neutral_ct, TRUE, TRUE],
|
||||
[$forbidden_ct, 'AND', $neutral_cf, TRUE, TRUE],
|
||||
[$forbidden_ct, 'AND', $neutral_un, TRUE, TRUE],
|
||||
// Forbidden (cf) AND neutral (ct,cf,un).
|
||||
[$forbidden_cf, 'AND', $neutral_ct, TRUE, FALSE],
|
||||
[$forbidden_cf, 'AND', $neutral_cf, TRUE, FALSE],
|
||||
[$forbidden_cf, 'AND', $neutral_un, TRUE, FALSE],
|
||||
// Forbidden (un) AND neutral (ct,cf,un).
|
||||
[$forbidden_un, 'AND', $neutral_ct, FALSE, NULL],
|
||||
[$forbidden_un, 'AND', $neutral_cf, FALSE, NULL],
|
||||
[$forbidden_un, 'AND', $neutral_un, FALSE, NULL],
|
||||
|
||||
// Forbidden (ct) AND forbidden (ct,cf,un).
|
||||
[$forbidden_ct, 'AND', $forbidden_ct, TRUE, TRUE],
|
||||
[$forbidden_ct, 'AND', $forbidden_cf, TRUE, TRUE],
|
||||
[$forbidden_ct, 'AND', $forbidden_un, TRUE, TRUE],
|
||||
// Forbidden (cf) AND forbidden (ct,cf,un).
|
||||
[$forbidden_cf, 'AND', $forbidden_ct, TRUE, FALSE],
|
||||
[$forbidden_cf, 'AND', $forbidden_cf, TRUE, FALSE],
|
||||
[$forbidden_cf, 'AND', $forbidden_un, TRUE, FALSE],
|
||||
// Forbidden (un) AND forbidden (ct,cf,un).
|
||||
[$forbidden_un, 'AND', $forbidden_ct, FALSE, NULL],
|
||||
[$forbidden_un, 'AND', $forbidden_cf, FALSE, NULL],
|
||||
[$forbidden_un, 'AND', $forbidden_un, FALSE, NULL],
|
||||
|
||||
|
||||
// Neutral (ct) AND allowed (ct,cf,un).
|
||||
[$neutral_ct, 'AND', $allowed_ct, TRUE, TRUE],
|
||||
[$neutral_ct, 'AND', $allowed_cf, TRUE, TRUE],
|
||||
[$neutral_ct, 'AND', $allowed_un, TRUE, TRUE],
|
||||
// Neutral (cf) AND allowed (ct,cf,un).
|
||||
[$neutral_cf, 'AND', $allowed_ct, TRUE, FALSE],
|
||||
[$neutral_cf, 'AND', $allowed_cf, TRUE, FALSE],
|
||||
[$neutral_cf, 'AND', $allowed_un, TRUE, FALSE],
|
||||
// Neutral (un) AND allowed (ct,cf,un).
|
||||
[$neutral_un, 'AND', $allowed_ct, FALSE, NULL],
|
||||
[$neutral_un, 'AND', $allowed_cf, FALSE, NULL],
|
||||
[$neutral_un, 'AND', $allowed_un, FALSE, NULL],
|
||||
|
||||
// Neutral (ct) AND neutral (ct,cf,un).
|
||||
[$neutral_ct, 'AND', $neutral_ct, TRUE, TRUE],
|
||||
[$neutral_ct, 'AND', $neutral_cf, TRUE, TRUE],
|
||||
[$neutral_ct, 'AND', $neutral_un, TRUE, TRUE],
|
||||
// Neutral (cf) AND neutral (ct,cf,un).
|
||||
[$neutral_cf, 'AND', $neutral_ct, TRUE, FALSE],
|
||||
[$neutral_cf, 'AND', $neutral_cf, TRUE, FALSE],
|
||||
[$neutral_cf, 'AND', $neutral_un, TRUE, FALSE],
|
||||
// Neutral (un) AND neutral (ct,cf,un).
|
||||
[$neutral_un, 'AND', $neutral_ct, FALSE, NULL],
|
||||
[$neutral_un, 'AND', $neutral_cf, FALSE, NULL],
|
||||
[$neutral_un, 'AND', $neutral_un, FALSE, NULL],
|
||||
|
||||
// Neutral (ct) AND forbidden (ct,cf,un).
|
||||
[$neutral_ct, 'AND', $forbidden_ct, TRUE, TRUE],
|
||||
[$neutral_ct, 'AND', $forbidden_cf, TRUE, FALSE],
|
||||
[$neutral_ct, 'AND', $forbidden_un, TRUE, FALSE],
|
||||
// Neutral (cf) AND forbidden (ct,cf,un).
|
||||
[$neutral_cf, 'AND', $forbidden_ct, TRUE, TRUE],
|
||||
[$neutral_cf, 'AND', $forbidden_cf, TRUE, FALSE],
|
||||
[$neutral_cf, 'AND', $forbidden_un, TRUE, FALSE],
|
||||
// Neutral (un) AND forbidden (ct,cf,un).
|
||||
[$neutral_un, 'AND', $forbidden_ct, FALSE, NULL],
|
||||
[$neutral_un, 'AND', $forbidden_cf, FALSE, NULL],
|
||||
[$neutral_un, 'AND', $forbidden_un, FALSE, NULL],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::andIf
|
||||
* @covers ::orIf
|
||||
* @covers ::inheritCacheability
|
||||
*
|
||||
* @dataProvider andOrCacheabilityPropagationProvider
|
||||
*/
|
||||
public function testAndOrCacheabilityPropagation(AccessResultInterface $first, $op, AccessResultInterface $second, $implements_cacheable_dependency_interface, $is_cacheable) {
|
||||
if ($op === 'OR') {
|
||||
$result = $first->orIf($second);
|
||||
}
|
||||
else if ($op === 'AND') {
|
||||
$result = $first->andIf($second);
|
||||
}
|
||||
else {
|
||||
throw new \LogicException('Invalid operator specified');
|
||||
}
|
||||
if ($implements_cacheable_dependency_interface) {
|
||||
$this->assertTrue($result instanceof CacheableDependencyInterface, 'Result is an instance of CacheableDependencyInterface.');
|
||||
if ($result instanceof CacheableDependencyInterface) {
|
||||
$this->assertSame($is_cacheable, $result->getCacheMaxAge() !== 0, 'getCacheMaxAge() matches expectations.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->assertFalse($result instanceof CacheableDependencyInterface, 'Result is not an instance of CacheableDependencyInterface.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::orIf
|
||||
*
|
||||
* Tests the special case of ORing non-forbidden access results that are both
|
||||
* cacheable but have different cacheability metadata.
|
||||
* This is only the case for non-forbidden access results; we still abort the
|
||||
* ORing process as soon as a forbidden access result is encountered. This is
|
||||
* tested in ::testOrIf().
|
||||
*/
|
||||
public function testOrIfCacheabilityMerging() {
|
||||
$merge_both_directions = function(AccessResult $a, AccessResult $b) {
|
||||
// A globally cacheable access result.
|
||||
$a->setCacheMaxAge(3600);
|
||||
// Another access result that is cacheable per permissions.
|
||||
$b->setCacheMaxAge(86400)->cachePerPermissions();
|
||||
|
||||
$r1 = $a->orIf($b);
|
||||
$this->assertTrue($r1->getCacheMaxAge() === 3600);
|
||||
$this->assertSame(['user.permissions'], $r1->getCacheContexts());
|
||||
$r2 = $b->orIf($a);
|
||||
$this->assertTrue($r2->getCacheMaxAge() === 3600);
|
||||
$this->assertSame(['user.permissions'], $r2->getCacheContexts());
|
||||
};
|
||||
|
||||
// Merge either direction, get the same result.
|
||||
$merge_both_directions(AccessResult::allowed(), AccessResult::allowed());
|
||||
$merge_both_directions(AccessResult::allowed(), AccessResult::neutral());
|
||||
$merge_both_directions(AccessResult::neutral(), AccessResult::neutral());
|
||||
$merge_both_directions(AccessResult::neutral(), AccessResult::allowed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests allowedIfHasPermissions().
|
||||
*
|
||||
* @covers ::allowedIfHasPermissions
|
||||
*
|
||||
* @dataProvider providerTestAllowedIfHasPermissions
|
||||
*/
|
||||
public function testAllowedIfHasPermissions($permissions, $conjunction, $expected_access) {
|
||||
$account = $this->getMock('\Drupal\Core\Session\AccountInterface');
|
||||
$account->expects($this->any())
|
||||
->method('hasPermission')
|
||||
->willReturnMap([
|
||||
['allowed', TRUE],
|
||||
['denied', FALSE],
|
||||
]);
|
||||
|
||||
$access_result = AccessResult::allowedIfHasPermissions($account, $permissions, $conjunction);
|
||||
$this->assertEquals($expected_access, $access_result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for the testAllowedIfHasPermissions() method.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestAllowedIfHasPermissions() {
|
||||
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'])],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class UncacheableTestAccessResult implements AccessResultInterface {
|
||||
|
||||
/**
|
||||
* The access result value. 'ALLOWED', 'FORBIDDEN' or 'NEUTRAL'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Constructs a new UncacheableTestAccessResult object.
|
||||
*/
|
||||
public function __construct($value) {
|
||||
$this->value = $value;
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isAllowed() {
|
||||
return $this->value === 'ALLOWED';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isForbidden() {
|
||||
return $this->value === 'FORBIDDEN';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isNeutral() {
|
||||
return $this->value === 'NEUTRAL';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function orIf(AccessResultInterface $other) {
|
||||
if ($this->isForbidden() || $other->isForbidden()) {
|
||||
return new static('FORBIDDEN');
|
||||
}
|
||||
elseif ($this->isAllowed() || $other->isAllowed()) {
|
||||
return new static('ALLOWED');
|
||||
}
|
||||
else {
|
||||
return new static('NEUTRAL');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function andIf(AccessResultInterface $other) {
|
||||
if ($this->isForbidden() || $other->isForbidden()) {
|
||||
return new static('FORBIDDEN');
|
||||
}
|
||||
elseif ($this->isAllowed() && $other->isAllowed()) {
|
||||
return new static('ALLOWED');
|
||||
}
|
||||
else {
|
||||
return new static('NEUTRAL');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
91
core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php
Normal file
91
core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Access\CsrfAccessCheckTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Drupal\Core\Access\CsrfAccessCheck;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Access\CsrfAccessCheck
|
||||
* @group Access
|
||||
*/
|
||||
class CsrfAccessCheckTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The mock CSRF token generator.
|
||||
*
|
||||
* @var \Drupal\Core\Access\CsrfTokenGenerator|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $csrfToken;
|
||||
|
||||
/**
|
||||
* The access checker.
|
||||
*
|
||||
* @var \Drupal\Core\Access\CsrfAccessCheck
|
||||
*/
|
||||
protected $accessCheck;
|
||||
|
||||
/**
|
||||
* The mock route match.
|
||||
*
|
||||
* @var \Drupal\Core\RouteMatch\RouteMatchInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $routeMatch;
|
||||
|
||||
protected function setUp() {
|
||||
$this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->routeMatch = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
|
||||
|
||||
$this->accessCheck = new CsrfAccessCheck($this->csrfToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the access() method with a valid token.
|
||||
*/
|
||||
public function testAccessTokenPass() {
|
||||
$this->csrfToken->expects($this->once())
|
||||
->method('validate')
|
||||
->with('test_query', 'test-path/42')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$this->routeMatch->expects($this->once())
|
||||
->method('getRawParameters')
|
||||
->will($this->returnValue(array('node' => 42)));
|
||||
|
||||
$route = new Route('/test-path/{node}', array(), array('_csrf_token' => 'TRUE'));
|
||||
$request = Request::create('/test-path/42?token=test_query');
|
||||
|
||||
$this->assertEquals(AccessResult::allowed()->setCacheMaxAge(0), $this->accessCheck->access($route, $request, $this->routeMatch));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the access() method with an invalid token.
|
||||
*/
|
||||
public function testAccessTokenFail() {
|
||||
$this->csrfToken->expects($this->once())
|
||||
->method('validate')
|
||||
->with('test_query', 'test-path')
|
||||
->will($this->returnValue(FALSE));
|
||||
|
||||
$this->routeMatch->expects($this->once())
|
||||
->method('getRawParameters')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$route = new Route('/test-path', array(), array('_csrf_token' => 'TRUE'));
|
||||
$request = Request::create('/test-path?token=test_query');
|
||||
|
||||
$this->assertEquals(AccessResult::forbidden()->setCacheMaxAge(0), $this->accessCheck->access($route, $request, $this->routeMatch));
|
||||
}
|
||||
|
||||
}
|
216
core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php
Normal file
216
core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php
Normal file
|
@ -0,0 +1,216 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Access\CsrfTokenGeneratorTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Access;
|
||||
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Core\Access\CsrfTokenGenerator;
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Tests the CsrfTokenGenerator class.
|
||||
*
|
||||
* @group Access
|
||||
* @coversDefaultClass \Drupal\Core\Access\CsrfTokenGenerator
|
||||
*/
|
||||
class CsrfTokenGeneratorTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The CSRF token generator.
|
||||
*
|
||||
* @var \Drupal\Core\Access\CsrfTokenGenerator
|
||||
*/
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* The mock private key instance.
|
||||
*
|
||||
* @var \Drupal\Core\PrivateKey|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $privateKey;
|
||||
|
||||
/**
|
||||
* The mock session metadata bag.
|
||||
*
|
||||
* @var \Drupal\Core\Session\MetadataBag|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $sessionMetadata;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->privateKey = $this->getMockBuilder('Drupal\Core\PrivateKey')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('get'))
|
||||
->getMock();
|
||||
|
||||
$this->sessionMetadata = $this->getMockBuilder('Drupal\Core\Session\MetadataBag')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$settings = array(
|
||||
'hash_salt' => $this->randomMachineName(),
|
||||
);
|
||||
|
||||
new Settings($settings);
|
||||
|
||||
$this->generator = new CsrfTokenGenerator($this->privateKey, $this->sessionMetadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up default expectations on the mocks.
|
||||
*/
|
||||
protected function setupDefaultExpectations() {
|
||||
$key = Crypt::randomBytesBase64();
|
||||
$this->privateKey->expects($this->any())
|
||||
->method('get')
|
||||
->will($this->returnValue($key));
|
||||
|
||||
$seed = Crypt::randomBytesBase64();
|
||||
$this->sessionMetadata->expects($this->any())
|
||||
->method('getCsrfTokenSeed')
|
||||
->will($this->returnValue($seed));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests CsrfTokenGenerator::get().
|
||||
*
|
||||
* @covers ::get
|
||||
*/
|
||||
public function testGet() {
|
||||
$this->setupDefaultExpectations();
|
||||
|
||||
$this->assertInternalType('string', $this->generator->get());
|
||||
$this->assertNotSame($this->generator->get(), $this->generator->get($this->randomMachineName()));
|
||||
$this->assertNotSame($this->generator->get($this->randomMachineName()), $this->generator->get($this->randomMachineName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a new token seed is generated upon first use.
|
||||
*
|
||||
* @covers ::get
|
||||
*/
|
||||
public function testGenerateSeedOnGet() {
|
||||
$key = Crypt::randomBytesBase64();
|
||||
$this->privateKey->expects($this->any())
|
||||
->method('get')
|
||||
->will($this->returnValue($key));
|
||||
|
||||
$this->sessionMetadata->expects($this->once())
|
||||
->method('getCsrfTokenSeed')
|
||||
->will($this->returnValue(NULL));
|
||||
|
||||
$this->sessionMetadata->expects($this->once())
|
||||
->method('setCsrfTokenSeed')
|
||||
->with($this->isType('string'));
|
||||
|
||||
$this->assertInternalType('string', $this->generator->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests CsrfTokenGenerator::validate().
|
||||
*
|
||||
* @covers ::validate
|
||||
*/
|
||||
public function testValidate() {
|
||||
$this->setupDefaultExpectations();
|
||||
|
||||
$token = $this->generator->get();
|
||||
$this->assertTrue($this->generator->validate($token));
|
||||
$this->assertFalse($this->generator->validate($token, 'foo'));
|
||||
|
||||
$token = $this->generator->get('bar');
|
||||
$this->assertTrue($this->generator->validate($token, 'bar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests CsrfTokenGenerator::validate() with different parameter types.
|
||||
*
|
||||
* @param mixed $token
|
||||
* The token to be validated.
|
||||
* @param mixed $value
|
||||
* (optional) An additional value to base the token on.
|
||||
*
|
||||
* @covers ::validate
|
||||
* @dataProvider providerTestValidateParameterTypes
|
||||
*/
|
||||
public function testValidateParameterTypes($token, $value) {
|
||||
$this->setupDefaultExpectations();
|
||||
|
||||
// The following check might throw PHP fatals and notices, so we disable
|
||||
// error assertions.
|
||||
set_error_handler(function () {return TRUE;});
|
||||
$this->assertFalse($this->generator->validate($token, $value));
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for testValidateParameterTypes.
|
||||
*
|
||||
* @return array
|
||||
* An array of data used by the test.
|
||||
*/
|
||||
public function providerTestValidateParameterTypes() {
|
||||
return array(
|
||||
array(array(), ''),
|
||||
array(TRUE, 'foo'),
|
||||
array(0, 'foo'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests CsrfTokenGenerator::validate() with invalid parameter types.
|
||||
*
|
||||
* @param mixed $token
|
||||
* The token to be validated.
|
||||
* @param mixed $value
|
||||
* (optional) An additional value to base the token on.
|
||||
*
|
||||
* @covers ::validate
|
||||
* @dataProvider providerTestInvalidParameterTypes
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidParameterTypes($token, $value = '') {
|
||||
$this->setupDefaultExpectations();
|
||||
|
||||
$this->generator->validate($token, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for testInvalidParameterTypes.
|
||||
*
|
||||
* @return array
|
||||
* An array of data used by the test.
|
||||
*/
|
||||
public function providerTestInvalidParameterTypes() {
|
||||
return array(
|
||||
array(NULL, new \stdClass()),
|
||||
array(0, array()),
|
||||
array('', array()),
|
||||
array(array(), array()),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the exception thrown when no 'hash_salt' is provided in settings.
|
||||
*
|
||||
* @covers ::get
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testGetWithNoHashSalt() {
|
||||
// Update settings with no hash salt.
|
||||
new Settings(array());
|
||||
$generator = new CsrfTokenGenerator($this->privateKey, $this->sessionMetadata);
|
||||
$generator->get();
|
||||
}
|
||||
|
||||
}
|
125
core/tests/Drupal/Tests/Core/Access/CustomAccessCheckTest.php
Normal file
125
core/tests/Drupal/Tests/Core/Access/CustomAccessCheckTest.php
Normal file
|
@ -0,0 +1,125 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Access\CustomAccessCheckTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Access\CustomAccessCheck;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Access\CustomAccessCheck
|
||||
* @group Access
|
||||
*/
|
||||
class CustomAccessCheckTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The access checker to test.
|
||||
*
|
||||
* @var \Drupal\Core\Access\CustomAccessCheck
|
||||
*/
|
||||
protected $accessChecker;
|
||||
|
||||
/**
|
||||
* The mocked controller resolver.
|
||||
*
|
||||
* @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $controllerResolver;
|
||||
|
||||
/**
|
||||
* The mocked arguments resolver.
|
||||
*
|
||||
* @var \Drupal\Core\Access\AccessArgumentsResolverFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $argumentsResolverFactory;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->controllerResolver = $this->getMock('Drupal\Core\Controller\ControllerResolverInterface');
|
||||
$this->argumentsResolverFactory = $this->getMock('Drupal\Core\Access\AccessArgumentsResolverFactoryInterface');
|
||||
$this->accessChecker = new CustomAccessCheck($this->controllerResolver, $this->argumentsResolverFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the access method.
|
||||
*/
|
||||
public function testAccess() {
|
||||
$route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
|
||||
|
||||
$this->controllerResolver->expects($this->at(0))
|
||||
->method('getControllerFromDefinition')
|
||||
->with('\Drupal\Tests\Core\Access\TestController::accessDeny')
|
||||
->will($this->returnValue(array(new TestController(), 'accessDeny')));
|
||||
|
||||
$resolver0 = $this->getMock('Drupal\Component\Utility\ArgumentsResolverInterface');
|
||||
$resolver0->expects($this->once())
|
||||
->method('getArguments')
|
||||
->will($this->returnValue(array()));
|
||||
$this->argumentsResolverFactory->expects($this->at(0))
|
||||
->method('getArgumentsResolver')
|
||||
->will($this->returnValue($resolver0));
|
||||
|
||||
$this->controllerResolver->expects($this->at(1))
|
||||
->method('getControllerFromDefinition')
|
||||
->with('\Drupal\Tests\Core\Access\TestController::accessAllow')
|
||||
->will($this->returnValue(array(new TestController(), 'accessAllow')));
|
||||
|
||||
$resolver1 = $this->getMock('Drupal\Component\Utility\ArgumentsResolverInterface');
|
||||
$resolver1->expects($this->once())
|
||||
->method('getArguments')
|
||||
->will($this->returnValue(array()));
|
||||
$this->argumentsResolverFactory->expects($this->at(1))
|
||||
->method('getArgumentsResolver')
|
||||
->will($this->returnValue($resolver1));
|
||||
|
||||
$this->controllerResolver->expects($this->at(2))
|
||||
->method('getControllerFromDefinition')
|
||||
->with('\Drupal\Tests\Core\Access\TestController::accessParameter')
|
||||
->will($this->returnValue(array(new TestController(), 'accessParameter')));
|
||||
|
||||
$resolver2 = $this->getMock('Drupal\Component\Utility\ArgumentsResolverInterface');
|
||||
$resolver2->expects($this->once())
|
||||
->method('getArguments')
|
||||
->will($this->returnValue(array('parameter' => 'TRUE')));
|
||||
$this->argumentsResolverFactory->expects($this->at(2))
|
||||
->method('getArgumentsResolver')
|
||||
->will($this->returnValue($resolver2));
|
||||
|
||||
$route = new Route('/test-route', array(), array('_custom_access' => '\Drupal\Tests\Core\Access\TestController::accessDeny'));
|
||||
$account = $this->getMock('Drupal\Core\Session\AccountInterface');
|
||||
$this->assertEquals(AccessResult::neutral(), $this->accessChecker->access($route, $route_match, $account));
|
||||
|
||||
$route = new Route('/test-route', array(), array('_custom_access' => '\Drupal\Tests\Core\Access\TestController::accessAllow'));
|
||||
$this->assertEquals(AccessResult::allowed(), $this->accessChecker->access($route, $route_match, $account));
|
||||
|
||||
$route = new Route('/test-route', array('parameter' => 'TRUE'), array('_custom_access' => '\Drupal\Tests\Core\Access\TestController::accessParameter'));
|
||||
$this->assertEquals(AccessResult::allowed(), $this->accessChecker->access($route, $route_match, $account));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestController {
|
||||
|
||||
public function accessAllow() {
|
||||
return AccessResult::allowed();
|
||||
}
|
||||
|
||||
public function accessDeny() {
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
public function accessParameter($parameter) {
|
||||
return AccessResult::allowedIf($parameter == 'TRUE');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Access\DefaultAccessCheckTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Access\DefaultAccessCheck;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Access\DefaultAccessCheck
|
||||
* @group Access
|
||||
*/
|
||||
class DefaultAccessCheckTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The access checker to test.
|
||||
*
|
||||
* @var \Drupal\Core\Access\DefaultAccessCheck
|
||||
*/
|
||||
protected $accessChecker;
|
||||
|
||||
/**
|
||||
* The mocked account.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
|
||||
$this->accessChecker = new DefaultAccessCheck();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the access method.
|
||||
*/
|
||||
public function testAccess() {
|
||||
$request = new Request(array());
|
||||
|
||||
$route = new Route('/test-route', array(), array('_access' => 'NULL'));
|
||||
$this->assertEquals(AccessResult::neutral(), $this->accessChecker->access($route, $request, $this->account));
|
||||
|
||||
$route = new Route('/test-route', array(), array('_access' => 'FALSE'));
|
||||
$this->assertEquals(AccessResult::forbidden(), $this->accessChecker->access($route, $request, $this->account));
|
||||
|
||||
$route = new Route('/test-route', array(), array('_access' => 'TRUE'));
|
||||
$this->assertEquals(AccessResult::allowed(), $this->accessChecker->access($route, $request, $this->account));
|
||||
}
|
||||
|
||||
}
|
120
core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php
Normal file
120
core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Access\RouteProcessorCsrfTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Access;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Core\Access\RouteProcessorCsrf;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Access\RouteProcessorCsrf
|
||||
* @group Access
|
||||
*/
|
||||
class RouteProcessorCsrfTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The mock CSRF token generator.
|
||||
*
|
||||
* @var \Drupal\Core\Access\CsrfTokenGenerator|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $csrfToken;
|
||||
|
||||
/**
|
||||
* The route processor.
|
||||
*
|
||||
* @var \Drupal\Core\Access\RouteProcessorCsrf
|
||||
*/
|
||||
protected $processor;
|
||||
|
||||
protected function setUp() {
|
||||
$this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->processor = new RouteProcessorCsrf($this->csrfToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the processOutbound() method with no _csrf_token route requirement.
|
||||
*/
|
||||
public function testProcessOutboundNoRequirement() {
|
||||
$this->csrfToken->expects($this->never())
|
||||
->method('get');
|
||||
|
||||
$route = new Route('/test-path');
|
||||
$parameters = array();
|
||||
|
||||
$cacheable_metadata = new CacheableMetadata();
|
||||
$this->processor->processOutbound('test', $route, $parameters, $cacheable_metadata);
|
||||
// No parameters should be added to the parameters array.
|
||||
$this->assertEmpty($parameters);
|
||||
// Cacheability of routes without a _csrf_token route requirement is
|
||||
// unaffected.
|
||||
$this->assertEquals((new CacheableMetadata()), $cacheable_metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the processOutbound() method with a _csrf_token route requirement.
|
||||
*/
|
||||
public function testProcessOutbound() {
|
||||
$this->csrfToken->expects($this->once())
|
||||
->method('get')
|
||||
// The leading '/' will be stripped from the path.
|
||||
->with('test-path')
|
||||
->will($this->returnValue('test_token'));
|
||||
|
||||
$route = new Route('/test-path', array(), array('_csrf_token' => 'TRUE'));
|
||||
$parameters = array();
|
||||
|
||||
$cacheable_metadata = new CacheableMetadata();
|
||||
$this->processor->processOutbound('test', $route, $parameters, $cacheable_metadata);
|
||||
// 'token' should be added to the parameters array.
|
||||
$this->assertArrayHasKey('token', $parameters);
|
||||
$this->assertSame($parameters['token'], 'test_token');
|
||||
// Cacheability of routes with a _csrf_token route requirement is max-age=0.
|
||||
$this->assertEquals((new CacheableMetadata())->setCacheMaxAge(0), $cacheable_metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the processOutbound() method with a dynamic path and one replacement.
|
||||
*/
|
||||
public function testProcessOutboundDynamicOne() {
|
||||
$this->csrfToken->expects($this->once())
|
||||
->method('get')
|
||||
->with('test-path/100')
|
||||
->will($this->returnValue('test_token'));
|
||||
|
||||
$route = new Route('/test-path/{slug}', array(), array('_csrf_token' => 'TRUE'));
|
||||
$parameters = array('slug' => 100);
|
||||
|
||||
$cacheable_metadata = new CacheableMetadata();
|
||||
$this->processor->processOutbound('test', $route, $parameters, $cacheable_metadata);
|
||||
// Cacheability of routes with a _csrf_token route requirement is max-age=0.
|
||||
$this->assertEquals((new CacheableMetadata())->setCacheMaxAge(0), $cacheable_metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the processOutbound() method with two parameter replacements.
|
||||
*/
|
||||
public function testProcessOutboundDynamicTwo() {
|
||||
$this->csrfToken->expects($this->once())
|
||||
->method('get')
|
||||
->with('100/test-path/test')
|
||||
->will($this->returnValue('test_token'));
|
||||
|
||||
$route = new Route('{slug_1}/test-path/{slug_2}', array(), array('_csrf_token' => 'TRUE'));
|
||||
$parameters = array('slug_1' => 100, 'slug_2' => 'test');
|
||||
|
||||
$cacheable_metadata = new CacheableMetadata();
|
||||
$this->processor->processOutbound('test', $route, $parameters, $cacheable_metadata);
|
||||
// Cacheability of routes with a _csrf_token route requirement is max-age=0.
|
||||
$this->assertEquals((new CacheableMetadata())->setCacheMaxAge(0), $cacheable_metadata);
|
||||
}
|
||||
|
||||
}
|
437
core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php
Normal file
437
core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php
Normal file
|
@ -0,0 +1,437 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Ajax\AjaxCommandsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Ajax;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Core\Ajax\AddCssCommand;
|
||||
use Drupal\Core\Ajax\AfterCommand;
|
||||
use Drupal\Core\Ajax\AlertCommand;
|
||||
use Drupal\Core\Ajax\AppendCommand;
|
||||
use Drupal\Core\Ajax\BeforeCommand;
|
||||
use Drupal\Core\Ajax\ChangedCommand;
|
||||
use Drupal\Core\Ajax\CssCommand;
|
||||
use Drupal\Core\Ajax\DataCommand;
|
||||
use Drupal\Core\Ajax\HtmlCommand;
|
||||
use Drupal\Core\Ajax\InsertCommand;
|
||||
use Drupal\Core\Ajax\InvokeCommand;
|
||||
use Drupal\Core\Ajax\PrependCommand;
|
||||
use Drupal\Core\Ajax\RemoveCommand;
|
||||
use Drupal\Core\Ajax\ReplaceCommand;
|
||||
use Drupal\Core\Ajax\RestripeCommand;
|
||||
use Drupal\Core\Ajax\SettingsCommand;
|
||||
use Drupal\Core\Ajax\CloseDialogCommand;
|
||||
use Drupal\Core\Ajax\CloseModalDialogCommand;
|
||||
use Drupal\Core\Ajax\SetDialogOptionCommand;
|
||||
use Drupal\Core\Ajax\SetDialogTitleCommand;
|
||||
use Drupal\Core\Ajax\RedirectCommand;
|
||||
|
||||
/**
|
||||
* Test coverage for various classes in the \Drupal\Core\Ajax namespace.
|
||||
*
|
||||
* @group Ajax
|
||||
*/
|
||||
class AjaxCommandsTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\AddCssCommand
|
||||
*/
|
||||
public function testAddCssCommand() {
|
||||
$command = new AddCssCommand('p{ text-decoration:blink; }');
|
||||
|
||||
$expected = array(
|
||||
'command' => 'add_css',
|
||||
'data' => 'p{ text-decoration:blink; }',
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\AfterCommand
|
||||
*/
|
||||
public function testAfterCommand() {
|
||||
$command = new AfterCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
|
||||
|
||||
$expected = array(
|
||||
'command' => 'insert',
|
||||
'method' => 'after',
|
||||
'selector' => '#page-title',
|
||||
'data' => '<p>New Text!</p>',
|
||||
'settings' => array('my-setting' => 'setting'),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\AlertCommand
|
||||
*/
|
||||
public function testAlertCommand() {
|
||||
$command = new AlertCommand('Set condition 1 throughout the ship!');
|
||||
$expected = array(
|
||||
'command' => 'alert',
|
||||
'text' => 'Set condition 1 throughout the ship!',
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\AppendCommand
|
||||
*/
|
||||
public function testAppendCommand() {
|
||||
$command = new AppendCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
|
||||
|
||||
$expected = array(
|
||||
'command' => 'insert',
|
||||
'method' => 'append',
|
||||
'selector' => '#page-title',
|
||||
'data' => '<p>New Text!</p>',
|
||||
'settings' => array('my-setting' => 'setting'),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\BeforeCommand
|
||||
*/
|
||||
public function testBeforeCommand() {
|
||||
$command = new BeforeCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
|
||||
|
||||
$expected = array(
|
||||
'command' => 'insert',
|
||||
'method' => 'before',
|
||||
'selector' => '#page-title',
|
||||
'data' => '<p>New Text!</p>',
|
||||
'settings' => array('my-setting' => 'setting'),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\ChangedCommand
|
||||
*/
|
||||
public function testChangedCommand() {
|
||||
$command = new ChangedCommand('#page-title', '#page-title-changed');
|
||||
|
||||
$expected = array(
|
||||
'command' => 'changed',
|
||||
'selector' => '#page-title',
|
||||
'asterisk' => '#page-title-changed',
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\CssCommand
|
||||
*/
|
||||
public function testCssCommand() {
|
||||
$command = new CssCommand('#page-title', array('text-decoration' => 'blink'));
|
||||
$command->setProperty('font-size', '40px')->setProperty('font-weight', 'bold');
|
||||
|
||||
$expected = array(
|
||||
'command' => 'css',
|
||||
'selector' => '#page-title',
|
||||
'argument' => array(
|
||||
'text-decoration' => 'blink',
|
||||
'font-size' => '40px',
|
||||
'font-weight' => 'bold',
|
||||
),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\DataCommand
|
||||
*/
|
||||
public function testDataCommand() {
|
||||
$command = new DataCommand('#page-title', 'my-data', array('key' => 'value'));
|
||||
|
||||
$expected = array(
|
||||
'command' => 'data',
|
||||
'selector' => '#page-title',
|
||||
'name' => 'my-data',
|
||||
'value' => array('key' => 'value'),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\HtmlCommand
|
||||
*/
|
||||
public function testHtmlCommand() {
|
||||
$command = new HtmlCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
|
||||
|
||||
$expected = array(
|
||||
'command' => 'insert',
|
||||
'method' => 'html',
|
||||
'selector' => '#page-title',
|
||||
'data' => '<p>New Text!</p>',
|
||||
'settings' => array('my-setting' => 'setting'),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\InsertCommand
|
||||
*/
|
||||
public function testInsertCommand() {
|
||||
$command = new InsertCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
|
||||
|
||||
$expected = array(
|
||||
'command' => 'insert',
|
||||
'method' => NULL,
|
||||
'selector' => '#page-title',
|
||||
'data' => '<p>New Text!</p>',
|
||||
'settings' => array('my-setting' => 'setting'),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\InvokeCommand
|
||||
*/
|
||||
public function testInvokeCommand() {
|
||||
$command = new InvokeCommand('#page-title', 'myMethod', array('var1', 'var2'));
|
||||
|
||||
$expected = array(
|
||||
'command' => 'invoke',
|
||||
'selector' => '#page-title',
|
||||
'method' => 'myMethod',
|
||||
'args' => array('var1', 'var2'),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\PrependCommand
|
||||
*/
|
||||
public function testPrependCommand() {
|
||||
$command = new PrependCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
|
||||
|
||||
$expected = array(
|
||||
'command' => 'insert',
|
||||
'method' => 'prepend',
|
||||
'selector' => '#page-title',
|
||||
'data' => '<p>New Text!</p>',
|
||||
'settings' => array('my-setting' => 'setting'),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\RemoveCommand
|
||||
*/
|
||||
public function testRemoveCommand() {
|
||||
$command = new RemoveCommand('#page-title');
|
||||
|
||||
$expected = array(
|
||||
'command' => 'remove',
|
||||
'selector' => '#page-title',
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\ReplaceCommand
|
||||
*/
|
||||
public function testReplaceCommand() {
|
||||
$command = new ReplaceCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
|
||||
|
||||
$expected = array(
|
||||
'command' => 'insert',
|
||||
'method' => 'replaceWith',
|
||||
'selector' => '#page-title',
|
||||
'data' => '<p>New Text!</p>',
|
||||
'settings' => array('my-setting' => 'setting'),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\RestripeCommand
|
||||
*/
|
||||
public function testRestripeCommand() {
|
||||
$command = new RestripeCommand('#page-title');
|
||||
|
||||
$expected = array(
|
||||
'command' => 'restripe',
|
||||
'selector' => '#page-title',
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\SettingsCommand
|
||||
*/
|
||||
public function testSettingsCommand() {
|
||||
$command = new SettingsCommand(array('key' => 'value'), TRUE);
|
||||
|
||||
$expected = array(
|
||||
'command' => 'settings',
|
||||
'settings' => array('key' => 'value'),
|
||||
'merge' => TRUE,
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\OpenDialogCommand
|
||||
*/
|
||||
public function testOpenDialogCommand() {
|
||||
$command = $this->getMockBuilder('Drupal\Core\Ajax\OpenDialogCommand')
|
||||
->setConstructorArgs(array(
|
||||
'#some-dialog', 'Title', '<p>Text!</p>', array(
|
||||
'url' => FALSE,
|
||||
'width' => 500,
|
||||
),
|
||||
))
|
||||
->setMethods(array('getRenderedContent'))
|
||||
->getMock();
|
||||
|
||||
// This method calls the render service, which isn't available. We want it
|
||||
// to do nothing so we mock it to return a known value.
|
||||
$command->expects($this->once())
|
||||
->method('getRenderedContent')
|
||||
->willReturn('rendered content');
|
||||
|
||||
$expected = array(
|
||||
'command' => 'openDialog',
|
||||
'selector' => '#some-dialog',
|
||||
'settings' => NULL,
|
||||
'data' => 'rendered content',
|
||||
'dialogOptions' => array(
|
||||
'url' => FALSE,
|
||||
'width' => 500,
|
||||
'title' => 'Title',
|
||||
'modal' => FALSE,
|
||||
),
|
||||
);
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\OpenModalDialogCommand
|
||||
*/
|
||||
public function testOpenModalDialogCommand() {
|
||||
$command = $this->getMockBuilder('Drupal\Core\Ajax\OpenModalDialogCommand')
|
||||
->setConstructorArgs(array(
|
||||
'Title', '<p>Text!</p>', array(
|
||||
'url' => 'example',
|
||||
'width' => 500,
|
||||
),
|
||||
))
|
||||
->setMethods(array('getRenderedContent'))
|
||||
->getMock();
|
||||
|
||||
// This method calls the render service, which isn't available. We want it
|
||||
// to do nothing so we mock it to return a known value.
|
||||
$command->expects($this->once())
|
||||
->method('getRenderedContent')
|
||||
->willReturn('rendered content');
|
||||
|
||||
$expected = array(
|
||||
'command' => 'openDialog',
|
||||
'selector' => '#drupal-modal',
|
||||
'settings' => NULL,
|
||||
'data' => 'rendered content',
|
||||
'dialogOptions' => array(
|
||||
'url' => 'example',
|
||||
'width' => 500,
|
||||
'title' => 'Title',
|
||||
'modal' => TRUE,
|
||||
),
|
||||
);
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\CloseModalDialogCommand
|
||||
*/
|
||||
public function testCloseModalDialogCommand() {
|
||||
$command = new CloseModalDialogCommand();
|
||||
$expected = array(
|
||||
'command' => 'closeDialog',
|
||||
'selector' => '#drupal-modal',
|
||||
'persist' => FALSE,
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\CloseDialogCommand
|
||||
*/
|
||||
public function testCloseDialogCommand() {
|
||||
$command = new CloseDialogCommand('#some-dialog', TRUE);
|
||||
$expected = array(
|
||||
'command' => 'closeDialog',
|
||||
'selector' => '#some-dialog',
|
||||
'persist' => TRUE,
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\SetDialogOptionCommand
|
||||
*/
|
||||
public function testSetDialogOptionCommand() {
|
||||
$command = new SetDialogOptionCommand('#some-dialog', 'width', '500');
|
||||
$expected = array(
|
||||
'command' => 'setDialogOption',
|
||||
'selector' => '#some-dialog',
|
||||
'optionName' => 'width',
|
||||
'optionValue' => '500',
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\SetDialogTitleCommand
|
||||
*/
|
||||
public function testSetDialogTitleCommand() {
|
||||
$command = new SetDialogTitleCommand('#some-dialog', 'Example');
|
||||
$expected = array(
|
||||
'command' => 'setDialogOption',
|
||||
'selector' => '#some-dialog',
|
||||
'optionName' => 'title',
|
||||
'optionValue' => 'Example',
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Ajax\RedirectCommand
|
||||
*/
|
||||
public function testRedirectCommand() {
|
||||
$command = new RedirectCommand('http://example.com');
|
||||
$expected = array(
|
||||
'command' => 'redirect',
|
||||
'url' => 'http://example.com',
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $command->render());
|
||||
}
|
||||
|
||||
}
|
101
core/tests/Drupal/Tests/Core/Ajax/AjaxResponseTest.php
Normal file
101
core/tests/Drupal/Tests/Core/Ajax/AjaxResponseTest.php
Normal file
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Ajax\AjaxResponseTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Ajax;
|
||||
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
|
||||
use Drupal\Core\Render\Element\Ajax;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Ajax\AjaxResponse
|
||||
* @group Ajax
|
||||
*/
|
||||
class AjaxResponseTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The tested ajax response object.
|
||||
*
|
||||
* @var \Drupal\Core\Ajax\AjaxResponse
|
||||
*/
|
||||
protected $ajaxResponse;
|
||||
|
||||
protected function setUp() {
|
||||
$this->ajaxResponse = new AjaxResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the add and getCommands method.
|
||||
*
|
||||
* @see \Drupal\Core\Ajax\AjaxResponse::addCommand()
|
||||
* @see \Drupal\Core\Ajax\AjaxResponse::getCommands()
|
||||
*/
|
||||
public function testCommands() {
|
||||
$command_one = $this->getMock('Drupal\Core\Ajax\CommandInterface');
|
||||
$command_one->expects($this->once())
|
||||
->method('render')
|
||||
->will($this->returnValue(array('command' => 'one')));
|
||||
$command_two = $this->getMock('Drupal\Core\Ajax\CommandInterface');
|
||||
$command_two->expects($this->once())
|
||||
->method('render')
|
||||
->will($this->returnValue(array('command' => 'two')));
|
||||
$command_three = $this->getMock('Drupal\Core\Ajax\CommandInterface');
|
||||
$command_three->expects($this->once())
|
||||
->method('render')
|
||||
->will($this->returnValue(array('command' => 'three')));
|
||||
|
||||
$this->ajaxResponse->addCommand($command_one);
|
||||
$this->ajaxResponse->addCommand($command_two);
|
||||
$this->ajaxResponse->addCommand($command_three, TRUE);
|
||||
|
||||
// Ensure that the added commands are in the right order.
|
||||
$commands =& $this->ajaxResponse->getCommands();
|
||||
$this->assertSame($commands[1], array('command' => 'one'));
|
||||
$this->assertSame($commands[2], array('command' => 'two'));
|
||||
$this->assertSame($commands[0], array('command' => 'three'));
|
||||
|
||||
// Remove one and change one element from commands and ensure the reference
|
||||
// worked as expected.
|
||||
unset($commands[2]);
|
||||
$commands[0]['class'] = 'test-class';
|
||||
|
||||
$commands = $this->ajaxResponse->getCommands();
|
||||
$this->assertSame($commands[1], array('command' => 'one'));
|
||||
$this->assertFalse(isset($commands[2]));
|
||||
$this->assertSame($commands[0], array('command' => 'three', 'class' => 'test-class'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the support for IE specific headers in file uploads.
|
||||
*
|
||||
* @cover ::prepareResponse
|
||||
*/
|
||||
public function testPrepareResponseForIeFormRequestsWithFileUpload() {
|
||||
$request = Request::create('/example', 'POST');
|
||||
$request->headers->set('Accept', 'text/html');
|
||||
$response = new AjaxResponse([]);
|
||||
$response->headers->set('Content-Type', 'application/json; charset=utf-8');
|
||||
|
||||
$ajax_response_attachments_processor = $this->getMock('\Drupal\Core\Render\AttachmentsResponseProcessorInterface');
|
||||
$subscriber = new AjaxResponseSubscriber($ajax_response_attachments_processor);
|
||||
$event = new FilterResponseEvent(
|
||||
$this->getMock('\Symfony\Component\HttpKernel\HttpKernelInterface'),
|
||||
$request,
|
||||
HttpKernelInterface::MASTER_REQUEST,
|
||||
$response
|
||||
);
|
||||
$subscriber->onResponse($event);
|
||||
$this->assertEquals('text/html; charset=utf-8', $response->headers->get('Content-Type'));
|
||||
$this->assertEquals($response->getContent(), '<textarea>[]</textarea>');
|
||||
}
|
||||
|
||||
|
||||
}
|
86
core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php
Normal file
86
core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Annotation\TranslationTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Annotation;
|
||||
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Annotation\Translation
|
||||
* @group Annotation
|
||||
*/
|
||||
class TranslationTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The translation manager used for testing.
|
||||
*
|
||||
* @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $translationManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->translationManager = $this->getStringTranslationStub();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::get
|
||||
*
|
||||
* @dataProvider providerTestGet
|
||||
*/
|
||||
public function testGet(array $values, $expected) {
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('string_translation', $this->translationManager);
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$arguments = isset($values['arguments']) ? $values['arguments'] : array();
|
||||
$options = isset($values['context']) ? array(
|
||||
'context' => $values['context'],
|
||||
) : array();
|
||||
$this->translationManager->expects($this->once())
|
||||
->method('translate')
|
||||
->with($values['value'], $arguments, $options);
|
||||
|
||||
$annotation = new Translation($values);
|
||||
|
||||
$this->assertSame($expected, (string) $annotation->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data to self::testGet().
|
||||
*/
|
||||
public function providerTestGet() {
|
||||
$data = array();
|
||||
$data[] = array(
|
||||
array(
|
||||
'value' => 'Foo',
|
||||
),
|
||||
'Foo'
|
||||
);
|
||||
$random = $this->randomMachineName();
|
||||
$random_html_entity = '&' . $random;
|
||||
$data[] = array(
|
||||
array(
|
||||
'value' => 'Foo !bar @baz %qux',
|
||||
'arguments' => array(
|
||||
'!bar' => $random,
|
||||
'@baz' => $random_html_entity,
|
||||
'%qux' => $random_html_entity,
|
||||
),
|
||||
'context' => $this->randomMachineName(),
|
||||
),
|
||||
'Foo ' . $random . ' &' . $random . ' <em class="placeholder">&' . $random . '</em>',
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Asset\CssCollectionGrouperUnitTest.
|
||||
*/
|
||||
|
||||
|
||||
namespace Drupal\Tests\Core\Asset;
|
||||
|
||||
use Drupal\Core\Asset\CssCollectionGrouper;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the CSS asset collection grouper.
|
||||
*
|
||||
* @group Asset
|
||||
*/
|
||||
class CssCollectionGrouperUnitTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* A CSS asset grouper.
|
||||
*
|
||||
* @var \Drupal\Core\Asset\CssCollectionGrouper object.
|
||||
*/
|
||||
protected $grouper;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->grouper = new CssCollectionGrouper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests \Drupal\Core\Asset\CssCollectionGrouper.
|
||||
*/
|
||||
function testGrouper() {
|
||||
$css_assets = array(
|
||||
'system.base.css' => array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.012,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => 'core/modules/system/system.base.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'system.base.css',
|
||||
),
|
||||
'system.theme.css' => array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.013,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => 'core/modules/system/system.theme.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'system.theme.css',
|
||||
),
|
||||
'jquery.ui.core.css' => array(
|
||||
'group' => -100,
|
||||
'type' => 'file',
|
||||
'weight' => 0.004,
|
||||
'every_page' => FALSE,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => 'core/misc/ui/themes/base/jquery.ui.core.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'jquery.ui.core.css',
|
||||
),
|
||||
'field.css' => array(
|
||||
'every_page' => TRUE,
|
||||
'group' => 0,
|
||||
'type' => 'file',
|
||||
'weight' => 0.011,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => 'core/modules/field/theme/field.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'field.css',
|
||||
),
|
||||
'external.css' => array(
|
||||
'every_page' => FALSE,
|
||||
'group' => 0,
|
||||
'type' => 'external',
|
||||
'weight' => 0.009,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => 'http://example.com/external.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'external.css',
|
||||
),
|
||||
'elements.css' => array(
|
||||
'group' => 100,
|
||||
'every_page' => TRUE,
|
||||
'media' => 'all',
|
||||
'type' => 'file',
|
||||
'weight' => 0.001,
|
||||
'preprocess' => TRUE,
|
||||
'data' => 'core/themes/bartik/css/base/elements.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'elements.css',
|
||||
),
|
||||
'print.css' => array(
|
||||
'group' => 100,
|
||||
'every_page' => TRUE,
|
||||
'media' => 'print',
|
||||
'type' => 'file',
|
||||
'weight' => 0.003,
|
||||
'preprocess' => TRUE,
|
||||
'data' => 'core/themes/bartik/css/print.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'print.css',
|
||||
),
|
||||
);
|
||||
|
||||
$groups = $this->grouper->group($css_assets);
|
||||
|
||||
$this->assertSame(count($groups), 6, "6 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']);
|
||||
|
||||
// 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']);
|
||||
|
||||
// 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']);
|
||||
|
||||
// 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']);
|
||||
|
||||
// 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']);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,507 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Asset\CssCollectionRendererUnitTest.
|
||||
*/
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* CssRenderer uses file_create_url(), which *is* available when using the
|
||||
* Simpletest test runner, but not when using the PHPUnit test runner; hence
|
||||
* this hack.
|
||||
*/
|
||||
if (!function_exists('file_create_url')) {
|
||||
|
||||
/**
|
||||
* Temporary mock for file_create_url(), until that is moved into
|
||||
* Component/Utility.
|
||||
*/
|
||||
function file_create_url($uri) {
|
||||
return 'file_create_url:' . $uri;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
namespace Drupal\Tests\Core\Asset {
|
||||
|
||||
use Drupal\Core\Asset\CssCollectionRenderer;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the CSS asset collection renderer.
|
||||
*
|
||||
* @group Asset
|
||||
*/
|
||||
class CssCollectionRendererUnitTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* A CSS asset renderer.
|
||||
*
|
||||
* @var \Drupal\Core\Asset\CssRenderer object.
|
||||
*/
|
||||
protected $renderer;
|
||||
|
||||
/**
|
||||
* A valid file CSS asset group.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fileCssGroup;
|
||||
|
||||
/**
|
||||
* The state mock class.
|
||||
*
|
||||
* @var \Drupal\Core\State\StateInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->state = $this->getMock('Drupal\Core\State\StateInterface');
|
||||
|
||||
$this->renderer = new CssCollectionRenderer($this->state);
|
||||
$this->fileCssGroup = array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'items' => array(
|
||||
0 => array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.012,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => 'tests/Drupal/Tests/Core/Asset/foo.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'foo.css',
|
||||
),
|
||||
1 => array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.013,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => 'tests/Drupal/Tests/Core/Asset/bar.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'bar.css',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for the CSS asset rendering test.
|
||||
*
|
||||
* @see testRender
|
||||
*/
|
||||
function providerTestRender() {
|
||||
$create_link_element = function($href, $media = 'all', $browsers = array()) {
|
||||
return array(
|
||||
'#type' => 'html_tag',
|
||||
'#tag' => 'link',
|
||||
'#attributes' => array(
|
||||
'rel' => 'stylesheet',
|
||||
'href' => $href,
|
||||
'media' => $media,
|
||||
),
|
||||
'#browsers' => $browsers,
|
||||
);
|
||||
};
|
||||
$create_style_element = function($value, $media, $browsers = array(), $wrap_in_cdata = FALSE) {
|
||||
$style_element = array(
|
||||
'#type' => 'html_tag',
|
||||
'#tag' => 'style',
|
||||
'#value' => $value,
|
||||
'#attributes' => array(
|
||||
'media' => $media
|
||||
),
|
||||
'#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(
|
||||
// Single external CSS asset.
|
||||
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()),
|
||||
),
|
||||
// Render elements.
|
||||
array(
|
||||
0 => $create_link_element('http://example.com/popular.js', 'all'),
|
||||
),
|
||||
),
|
||||
// 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()),
|
||||
),
|
||||
array(
|
||||
0 => $create_link_element(file_create_url('public://css/file-every_page-all') . '?0', 'all'),
|
||||
),
|
||||
),
|
||||
// 31 file CSS assets: expect 31 link elements.
|
||||
3 => array(
|
||||
array(
|
||||
0 => $create_file_css_asset('public://css/1.css'),
|
||||
1 => $create_file_css_asset('public://css/2.css'),
|
||||
2 => $create_file_css_asset('public://css/3.css'),
|
||||
3 => $create_file_css_asset('public://css/4.css'),
|
||||
4 => $create_file_css_asset('public://css/5.css'),
|
||||
5 => $create_file_css_asset('public://css/6.css'),
|
||||
6 => $create_file_css_asset('public://css/7.css'),
|
||||
7 => $create_file_css_asset('public://css/8.css'),
|
||||
8 => $create_file_css_asset('public://css/9.css'),
|
||||
9 => $create_file_css_asset('public://css/10.css'),
|
||||
10 => $create_file_css_asset('public://css/11.css'),
|
||||
11 => $create_file_css_asset('public://css/12.css'),
|
||||
12 => $create_file_css_asset('public://css/13.css'),
|
||||
13 => $create_file_css_asset('public://css/14.css'),
|
||||
14 => $create_file_css_asset('public://css/15.css'),
|
||||
15 => $create_file_css_asset('public://css/16.css'),
|
||||
16 => $create_file_css_asset('public://css/17.css'),
|
||||
17 => $create_file_css_asset('public://css/18.css'),
|
||||
18 => $create_file_css_asset('public://css/19.css'),
|
||||
19 => $create_file_css_asset('public://css/20.css'),
|
||||
20 => $create_file_css_asset('public://css/21.css'),
|
||||
21 => $create_file_css_asset('public://css/22.css'),
|
||||
22 => $create_file_css_asset('public://css/23.css'),
|
||||
23 => $create_file_css_asset('public://css/24.css'),
|
||||
24 => $create_file_css_asset('public://css/25.css'),
|
||||
25 => $create_file_css_asset('public://css/26.css'),
|
||||
26 => $create_file_css_asset('public://css/27.css'),
|
||||
27 => $create_file_css_asset('public://css/28.css'),
|
||||
28 => $create_file_css_asset('public://css/29.css'),
|
||||
29 => $create_file_css_asset('public://css/30.css'),
|
||||
30 => $create_file_css_asset('public://css/31.css'),
|
||||
),
|
||||
array(
|
||||
0 => $create_link_element(file_create_url('public://css/1.css') . '?0'),
|
||||
1 => $create_link_element(file_create_url('public://css/2.css') . '?0'),
|
||||
2 => $create_link_element(file_create_url('public://css/3.css') . '?0'),
|
||||
3 => $create_link_element(file_create_url('public://css/4.css') . '?0'),
|
||||
4 => $create_link_element(file_create_url('public://css/5.css') . '?0'),
|
||||
5 => $create_link_element(file_create_url('public://css/6.css') . '?0'),
|
||||
6 => $create_link_element(file_create_url('public://css/7.css') . '?0'),
|
||||
7 => $create_link_element(file_create_url('public://css/8.css') . '?0'),
|
||||
8 => $create_link_element(file_create_url('public://css/9.css') . '?0'),
|
||||
9 => $create_link_element(file_create_url('public://css/10.css') . '?0'),
|
||||
10 => $create_link_element(file_create_url('public://css/11.css') . '?0'),
|
||||
11 => $create_link_element(file_create_url('public://css/12.css') . '?0'),
|
||||
12 => $create_link_element(file_create_url('public://css/13.css') . '?0'),
|
||||
13 => $create_link_element(file_create_url('public://css/14.css') . '?0'),
|
||||
14 => $create_link_element(file_create_url('public://css/15.css') . '?0'),
|
||||
15 => $create_link_element(file_create_url('public://css/16.css') . '?0'),
|
||||
16 => $create_link_element(file_create_url('public://css/17.css') . '?0'),
|
||||
17 => $create_link_element(file_create_url('public://css/18.css') . '?0'),
|
||||
18 => $create_link_element(file_create_url('public://css/19.css') . '?0'),
|
||||
19 => $create_link_element(file_create_url('public://css/20.css') . '?0'),
|
||||
20 => $create_link_element(file_create_url('public://css/21.css') . '?0'),
|
||||
21 => $create_link_element(file_create_url('public://css/22.css') . '?0'),
|
||||
22 => $create_link_element(file_create_url('public://css/23.css') . '?0'),
|
||||
23 => $create_link_element(file_create_url('public://css/24.css') . '?0'),
|
||||
24 => $create_link_element(file_create_url('public://css/25.css') . '?0'),
|
||||
25 => $create_link_element(file_create_url('public://css/26.css') . '?0'),
|
||||
26 => $create_link_element(file_create_url('public://css/27.css') . '?0'),
|
||||
27 => $create_link_element(file_create_url('public://css/28.css') . '?0'),
|
||||
28 => $create_link_element(file_create_url('public://css/29.css') . '?0'),
|
||||
29 => $create_link_element(file_create_url('public://css/30.css') . '?0'),
|
||||
30 => $create_link_element(file_create_url('public://css/31.css') . '?0'),
|
||||
),
|
||||
),
|
||||
// 32 file CSS assets with the same properties: expect 2 style elements.
|
||||
4 => array(
|
||||
array(
|
||||
0 => $create_file_css_asset('public://css/1.css'),
|
||||
1 => $create_file_css_asset('public://css/2.css'),
|
||||
2 => $create_file_css_asset('public://css/3.css'),
|
||||
3 => $create_file_css_asset('public://css/4.css'),
|
||||
4 => $create_file_css_asset('public://css/5.css'),
|
||||
5 => $create_file_css_asset('public://css/6.css'),
|
||||
6 => $create_file_css_asset('public://css/7.css'),
|
||||
7 => $create_file_css_asset('public://css/8.css'),
|
||||
8 => $create_file_css_asset('public://css/9.css'),
|
||||
9 => $create_file_css_asset('public://css/10.css'),
|
||||
10 => $create_file_css_asset('public://css/11.css'),
|
||||
11 => $create_file_css_asset('public://css/12.css'),
|
||||
12 => $create_file_css_asset('public://css/13.css'),
|
||||
13 => $create_file_css_asset('public://css/14.css'),
|
||||
14 => $create_file_css_asset('public://css/15.css'),
|
||||
15 => $create_file_css_asset('public://css/16.css'),
|
||||
16 => $create_file_css_asset('public://css/17.css'),
|
||||
17 => $create_file_css_asset('public://css/18.css'),
|
||||
18 => $create_file_css_asset('public://css/19.css'),
|
||||
19 => $create_file_css_asset('public://css/20.css'),
|
||||
20 => $create_file_css_asset('public://css/21.css'),
|
||||
21 => $create_file_css_asset('public://css/22.css'),
|
||||
22 => $create_file_css_asset('public://css/23.css'),
|
||||
23 => $create_file_css_asset('public://css/24.css'),
|
||||
24 => $create_file_css_asset('public://css/25.css'),
|
||||
25 => $create_file_css_asset('public://css/26.css'),
|
||||
26 => $create_file_css_asset('public://css/27.css'),
|
||||
27 => $create_file_css_asset('public://css/28.css'),
|
||||
28 => $create_file_css_asset('public://css/29.css'),
|
||||
29 => $create_file_css_asset('public://css/30.css'),
|
||||
30 => $create_file_css_asset('public://css/31.css'),
|
||||
31 => $create_file_css_asset('public://css/32.css'),
|
||||
),
|
||||
array(
|
||||
0 => $create_style_element('
|
||||
@import url("' . file_create_url('public://css/1.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/2.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/3.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/4.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/5.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/6.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/7.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/8.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/9.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/10.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/11.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/12.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/13.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/14.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/15.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/16.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/17.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/18.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/19.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/20.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/21.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/22.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/23.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/24.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/25.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/26.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/27.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/28.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/29.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/30.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/31.css') . '?0");
|
||||
', 'all'),
|
||||
1 => $create_style_element('
|
||||
@import url("' . file_create_url('public://css/32.css') . '?0");
|
||||
', 'all'),
|
||||
),
|
||||
),
|
||||
// 32 file CSS assets with the same properties, except for the 10th and
|
||||
// 20th files, they have different 'media' properties. Expect 5 style
|
||||
// elements.
|
||||
5 => array(
|
||||
array(
|
||||
0 => $create_file_css_asset('public://css/1.css'),
|
||||
1 => $create_file_css_asset('public://css/2.css'),
|
||||
2 => $create_file_css_asset('public://css/3.css'),
|
||||
3 => $create_file_css_asset('public://css/4.css'),
|
||||
4 => $create_file_css_asset('public://css/5.css'),
|
||||
5 => $create_file_css_asset('public://css/6.css'),
|
||||
6 => $create_file_css_asset('public://css/7.css'),
|
||||
7 => $create_file_css_asset('public://css/8.css'),
|
||||
8 => $create_file_css_asset('public://css/9.css'),
|
||||
9 => $create_file_css_asset('public://css/10.css', 'screen'),
|
||||
10 => $create_file_css_asset('public://css/11.css'),
|
||||
11 => $create_file_css_asset('public://css/12.css'),
|
||||
12 => $create_file_css_asset('public://css/13.css'),
|
||||
13 => $create_file_css_asset('public://css/14.css'),
|
||||
14 => $create_file_css_asset('public://css/15.css'),
|
||||
15 => $create_file_css_asset('public://css/16.css'),
|
||||
16 => $create_file_css_asset('public://css/17.css'),
|
||||
17 => $create_file_css_asset('public://css/18.css'),
|
||||
18 => $create_file_css_asset('public://css/19.css'),
|
||||
19 => $create_file_css_asset('public://css/20.css', 'print'),
|
||||
20 => $create_file_css_asset('public://css/21.css'),
|
||||
21 => $create_file_css_asset('public://css/22.css'),
|
||||
22 => $create_file_css_asset('public://css/23.css'),
|
||||
23 => $create_file_css_asset('public://css/24.css'),
|
||||
24 => $create_file_css_asset('public://css/25.css'),
|
||||
25 => $create_file_css_asset('public://css/26.css'),
|
||||
26 => $create_file_css_asset('public://css/27.css'),
|
||||
27 => $create_file_css_asset('public://css/28.css'),
|
||||
28 => $create_file_css_asset('public://css/29.css'),
|
||||
29 => $create_file_css_asset('public://css/30.css'),
|
||||
30 => $create_file_css_asset('public://css/31.css'),
|
||||
31 => $create_file_css_asset('public://css/32.css'),
|
||||
),
|
||||
array(
|
||||
0 => $create_style_element('
|
||||
@import url("' . file_create_url('public://css/1.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/2.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/3.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/4.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/5.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/6.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/7.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/8.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/9.css') . '?0");
|
||||
', 'all'),
|
||||
1 => $create_style_element('
|
||||
@import url("' . file_create_url('public://css/10.css') . '?0");
|
||||
', 'screen'),
|
||||
2 => $create_style_element('
|
||||
@import url("' . file_create_url('public://css/11.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/12.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/13.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/14.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/15.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/16.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/17.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/18.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/19.css') . '?0");
|
||||
', 'all'),
|
||||
3 => $create_style_element('
|
||||
@import url("' . file_create_url('public://css/20.css') . '?0");
|
||||
', 'print'),
|
||||
4 => $create_style_element('
|
||||
@import url("' . file_create_url('public://css/21.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/22.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/23.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/24.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/25.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/26.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/27.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/28.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/29.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/30.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/31.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/32.css') . '?0");
|
||||
', 'all'),
|
||||
),
|
||||
),
|
||||
// 32 file CSS assets with the same properties, except for the 15th, which
|
||||
// has 'preprocess' = FALSE. Expect 1 link element and 2 style elements.
|
||||
6 => array(
|
||||
array(
|
||||
0 => $create_file_css_asset('public://css/1.css'),
|
||||
1 => $create_file_css_asset('public://css/2.css'),
|
||||
2 => $create_file_css_asset('public://css/3.css'),
|
||||
3 => $create_file_css_asset('public://css/4.css'),
|
||||
4 => $create_file_css_asset('public://css/5.css'),
|
||||
5 => $create_file_css_asset('public://css/6.css'),
|
||||
6 => $create_file_css_asset('public://css/7.css'),
|
||||
7 => $create_file_css_asset('public://css/8.css'),
|
||||
8 => $create_file_css_asset('public://css/9.css'),
|
||||
9 => $create_file_css_asset('public://css/10.css'),
|
||||
10 => $create_file_css_asset('public://css/11.css'),
|
||||
11 => $create_file_css_asset('public://css/12.css'),
|
||||
12 => $create_file_css_asset('public://css/13.css'),
|
||||
13 => $create_file_css_asset('public://css/14.css'),
|
||||
14 => $create_file_css_asset('public://css/15.css', 'all', FALSE),
|
||||
15 => $create_file_css_asset('public://css/16.css'),
|
||||
16 => $create_file_css_asset('public://css/17.css'),
|
||||
17 => $create_file_css_asset('public://css/18.css'),
|
||||
18 => $create_file_css_asset('public://css/19.css'),
|
||||
19 => $create_file_css_asset('public://css/20.css'),
|
||||
20 => $create_file_css_asset('public://css/21.css'),
|
||||
21 => $create_file_css_asset('public://css/22.css'),
|
||||
22 => $create_file_css_asset('public://css/23.css'),
|
||||
23 => $create_file_css_asset('public://css/24.css'),
|
||||
24 => $create_file_css_asset('public://css/25.css'),
|
||||
25 => $create_file_css_asset('public://css/26.css'),
|
||||
26 => $create_file_css_asset('public://css/27.css'),
|
||||
27 => $create_file_css_asset('public://css/28.css'),
|
||||
28 => $create_file_css_asset('public://css/29.css'),
|
||||
29 => $create_file_css_asset('public://css/30.css'),
|
||||
30 => $create_file_css_asset('public://css/31.css'),
|
||||
31 => $create_file_css_asset('public://css/32.css'),
|
||||
),
|
||||
array(
|
||||
0 => $create_style_element('
|
||||
@import url("' . file_create_url('public://css/1.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/2.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/3.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/4.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/5.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/6.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/7.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/8.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/9.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/10.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/11.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/12.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/13.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/14.css') . '?0");
|
||||
', 'all'),
|
||||
1 => $create_link_element(file_create_url('public://css/15.css') . '?0'),
|
||||
2 => $create_style_element('
|
||||
@import url("' . file_create_url('public://css/16.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/17.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/18.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/19.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/20.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/21.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/22.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/23.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/24.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/25.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/26.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/27.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/28.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/29.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/30.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/31.css') . '?0");
|
||||
@import url("' . file_create_url('public://css/32.css') . '?0");
|
||||
', 'all'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests CSS asset rendering.
|
||||
*
|
||||
* @dataProvider providerTestRender
|
||||
*/
|
||||
function testRender(array $css_assets, array $render_elements) {
|
||||
$this->state->expects($this->once())
|
||||
->method('get')
|
||||
->with('system.css_js_query_string')
|
||||
->will($this->returnValue(NULL));
|
||||
$this->assertSame($render_elements, $this->renderer->render($css_assets));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a CSS asset group with the invalid 'type' => 'internal'.
|
||||
*/
|
||||
function testRenderInvalidType() {
|
||||
$this->state->expects($this->once())
|
||||
->method('get')
|
||||
->with('system.css_js_query_string')
|
||||
->will($this->returnValue(NULL));
|
||||
$this->setExpectedException('Exception', 'Invalid CSS asset type.');
|
||||
|
||||
$css_group = array(
|
||||
'group' => 0,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'internal',
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'browsers' => array(),
|
||||
'data' => 'http://example.com/popular.js'
|
||||
);
|
||||
$this->renderer->render($css_group);
|
||||
}
|
||||
}
|
||||
}
|
284
core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php
Normal file
284
core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php
Normal file
|
@ -0,0 +1,284 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Asset\CssOptimizerUnitTest.
|
||||
*/
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* CssOptimizer uses file_create_url(), which *is* available when using the
|
||||
* Simpletest test runner, but not when using the PHPUnit test runner; hence
|
||||
* this hack.
|
||||
*/
|
||||
if (!function_exists('file_create_url')) {
|
||||
|
||||
/**
|
||||
* Temporary mock for file_create_url(), until that is moved into
|
||||
* Component/Utility.
|
||||
*/
|
||||
function file_create_url($uri) {
|
||||
return 'file_create_url:' . $uri;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!function_exists('file_uri_scheme')) {
|
||||
|
||||
function file_uri_scheme($uri) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace Drupal\Tests\Core\Asset {
|
||||
|
||||
use Drupal\Core\Asset\CssOptimizer;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the CSS asset optimizer.
|
||||
*
|
||||
* @group Asset
|
||||
*/
|
||||
class CssOptimizerUnitTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* A CSS asset optimizer.
|
||||
*
|
||||
* @var \Drupal\Core\Asset\CssOptimizer object.
|
||||
*/
|
||||
protected $optimizer;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->optimizer = new CssOptimizer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for the CSS asset optimizing test.
|
||||
*/
|
||||
function providerTestOptimize() {
|
||||
$path = dirname(__FILE__) . '/css_test_files/';
|
||||
return array(
|
||||
// File. Tests:
|
||||
// - Stripped comments and white-space.
|
||||
// - Retain white-space in selectors. (https://www.drupal.org/node/472820)
|
||||
// - Retain pseudo-selectors. (https://www.drupal.org/node/460448)
|
||||
0 => array(
|
||||
array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.012,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'css_input_without_import.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'css_input_without_import.css',
|
||||
),
|
||||
file_get_contents($path . 'css_input_without_import.css.optimized.css'),
|
||||
),
|
||||
// File. Tests:
|
||||
// - Proper URLs in imported files. (https://www.drupal.org/node/265719)
|
||||
// - A background image with relative paths, which must be rewritten.
|
||||
// - The rewritten background image path must also be passed through
|
||||
// file_create_url(). (https://www.drupal.org/node/1961340)
|
||||
// - Imported files that are external (protocol-relative URL or not)
|
||||
// should not be expanded. (https://www.drupal.org/node/2014851)
|
||||
1 => array(
|
||||
array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.013,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'css_input_with_import.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'css_input_with_import.css',
|
||||
),
|
||||
str_replace('url(images/icon.png)', 'url(' . file_create_url($path . 'images/icon.png') . ')', file_get_contents($path . 'css_input_with_import.css.optimized.css')),
|
||||
),
|
||||
// File. Tests:
|
||||
// - Retain comment hacks.
|
||||
2 => array(
|
||||
array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.013,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'comment_hacks.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'comment_hacks.css',
|
||||
),
|
||||
file_get_contents($path . 'comment_hacks.css.optimized.css'),
|
||||
),
|
||||
// File in subfolder. Tests:
|
||||
// - CSS import path is properly interpreted.
|
||||
// (https://www.drupal.org/node/1198904)
|
||||
// - Don't adjust data URIs (https://www.drupal.org/node/2142441)
|
||||
5 => array(
|
||||
array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.013,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'css_subfolder/css_input_with_import.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'css_input_with_import.css',
|
||||
),
|
||||
str_replace('url(../images/icon.png)', 'url(' . file_create_url($path . 'images/icon.png') . ')', file_get_contents($path . 'css_subfolder/css_input_with_import.css.optimized.css')),
|
||||
),
|
||||
// File. Tests:
|
||||
// - Any @charaset declaration at the beginning of a file should be
|
||||
// removed without breaking subsequent CSS.
|
||||
6 => array(
|
||||
array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.013,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'charset_sameline.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'charset_sameline.css',
|
||||
),
|
||||
file_get_contents($path . 'charset.css.optimized.css'),
|
||||
),
|
||||
7 => array(
|
||||
array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.013,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'charset_newline.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'charset_newline.css',
|
||||
),
|
||||
file_get_contents($path . 'charset.css.optimized.css'),
|
||||
),
|
||||
6 => array(
|
||||
array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.013,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'css_input_with_bom.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'css_input_with_bom.css',
|
||||
),
|
||||
'.byte-order-mark-test{content:"☃";}'. "\n",
|
||||
),
|
||||
7 => array(
|
||||
array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.013,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'css_input_with_charset.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'css_input_with_charset.css',
|
||||
),
|
||||
'.charset-test{content:"€";}' . "\n",
|
||||
),
|
||||
8 => array(
|
||||
array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.013,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'css_input_with_bom_and_charset.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'css_input_with_bom_and_charset.css',
|
||||
),
|
||||
'.byte-order-mark-charset-test{content:"☃";}' . "\n",
|
||||
),
|
||||
9 => array(
|
||||
array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.013,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'css_input_with_utf16_bom.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'css_input_with_utf16_bom.css',
|
||||
),
|
||||
'.utf16-byte-order-mark-test{content:"☃";}' . "\n",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests optimizing a CSS asset group containing 'type' => 'file'.
|
||||
*
|
||||
* @dataProvider providerTestOptimize
|
||||
*/
|
||||
function testOptimize($css_asset, $expected) {
|
||||
$this->assertEquals($expected, $this->optimizer->optimize($css_asset), 'Group of file CSS assets optimized correctly.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a file CSS asset with preprocessing disabled.
|
||||
*/
|
||||
function testTypeFilePreprocessingDisabled() {
|
||||
$this->setExpectedException('Exception', 'Only file CSS assets with preprocessing enabled can be optimized.');
|
||||
|
||||
$css_asset = array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
'type' => 'file',
|
||||
'weight' => 0.012,
|
||||
'media' => 'all',
|
||||
// Preprocessing disabled.
|
||||
'preprocess' => FALSE,
|
||||
'data' => 'tests/Drupal/Tests/Core/Asset/foo.css',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
'basename' => 'foo.css',
|
||||
);
|
||||
$this->optimizer->optimize($css_asset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a CSS asset with 'type' => 'external'.
|
||||
*/
|
||||
function testTypeExternal() {
|
||||
$this->setExpectedException('Exception', 'Only file or inline CSS assets can be optimized.');
|
||||
|
||||
$css_asset = array(
|
||||
'group' => -100,
|
||||
'every_page' => TRUE,
|
||||
// Type external.
|
||||
'type' => 'external',
|
||||
'weight' => 0.012,
|
||||
'media' => 'all',
|
||||
'preprocess' => TRUE,
|
||||
'data' => 'http://example.com/foo.js',
|
||||
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
|
||||
);
|
||||
$this->optimizer->optimize($css_asset);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
131
core/tests/Drupal/Tests/Core/Asset/JsOptimizerUnitTest.php
Normal file
131
core/tests/Drupal/Tests/Core/Asset/JsOptimizerUnitTest.php
Normal file
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Asset\JsOptimizerUnitTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Asset;
|
||||
|
||||
use Drupal\Core\Asset\JsOptimizer;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the JS asset optimizer.
|
||||
*
|
||||
* @group Asset
|
||||
*/
|
||||
class JsOptimizerUnitTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* A JS asset optimizer.
|
||||
*
|
||||
* @var \Drupal\Core\Asset\JsOptimizer object.
|
||||
*/
|
||||
protected $optimizer;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->optimizer = new JsOptimizer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for the JS asset cleaning test.
|
||||
*
|
||||
* @see \Drupal\Core\Asset\JsOptimizer::clean().
|
||||
*
|
||||
* @returns array
|
||||
* An array of test data.
|
||||
*/
|
||||
function providerTestClean() {
|
||||
$path = dirname(__FILE__) . '/js_test_files/';
|
||||
return array(
|
||||
// File. Tests:
|
||||
// - Stripped sourceMappingURL with comment # syntax.
|
||||
0 => array(
|
||||
file_get_contents($path . 'source_mapping_url.min.js'),
|
||||
file_get_contents($path . 'source_mapping_url.min.js.optimized.js'),
|
||||
),
|
||||
// File. Tests:
|
||||
// - Stripped sourceMappingURL with comment @ syntax.
|
||||
1 => array(
|
||||
file_get_contents($path . 'source_mapping_url_old.min.js'),
|
||||
file_get_contents($path . 'source_mapping_url_old.min.js.optimized.js'),
|
||||
),
|
||||
// File. Tests:
|
||||
// - Stripped sourceURL with comment # syntax.
|
||||
2 => array(
|
||||
file_get_contents($path . 'source_url.min.js'),
|
||||
file_get_contents($path . 'source_url.min.js.optimized.js'),
|
||||
),
|
||||
// File. Tests:
|
||||
// - Stripped sourceURL with comment @ syntax.
|
||||
3 => array(
|
||||
file_get_contents($path . 'source_url_old.min.js'),
|
||||
file_get_contents($path . 'source_url_old.min.js.optimized.js'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests cleaning of a JS asset group containing 'type' => 'file'.
|
||||
*
|
||||
* @dataProvider providerTestClean
|
||||
*/
|
||||
function testClean($js_asset, $expected) {
|
||||
$this->assertEquals($expected, $this->optimizer->clean($js_asset));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for the JS asset optimize test.
|
||||
*
|
||||
* @see \Drupal\Core\Asset\JsOptimizer::optimize().
|
||||
*
|
||||
* @returns array
|
||||
* An array of test data.
|
||||
*/
|
||||
function providerTestOptimize() {
|
||||
$path = dirname(__FILE__) . '/js_test_files/';
|
||||
return array(
|
||||
0 => array(
|
||||
array(
|
||||
'type' => 'file',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'utf8_bom.js',
|
||||
),
|
||||
file_get_contents($path . 'utf8_bom.js.optimized.js'),
|
||||
),
|
||||
1 => array(
|
||||
array(
|
||||
'type' => 'file',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'utf16_bom.js',
|
||||
),
|
||||
file_get_contents($path . 'utf16_bom.js.optimized.js'),
|
||||
),
|
||||
2 => array(
|
||||
array(
|
||||
'type' => 'file',
|
||||
'preprocess' => TRUE,
|
||||
'data' => $path . 'latin_9.js',
|
||||
'attributes' => array('charset' => 'ISO-8859-15'),
|
||||
),
|
||||
file_get_contents($path . 'latin_9.js.optimized.js'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests cleaning of a JS asset group containing 'type' => 'file'.
|
||||
*
|
||||
* @dataProvider providerTestOptimize
|
||||
*/
|
||||
function testOptimize($js_asset, $expected) {
|
||||
$this->assertEquals($expected, $this->optimizer->optimize($js_asset));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Asset\LibraryDependencyResolverTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Asset;
|
||||
|
||||
use Drupal\Core\Asset\LibraryDependencyResolver;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Asset\LibraryDependencyResolver
|
||||
* @group Asset
|
||||
*/
|
||||
class LibraryDependencyResolverTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The tested library dependency resolver.
|
||||
*
|
||||
* @var \Drupal\Core\Asset\LibraryDependencyResolver
|
||||
*/
|
||||
protected $libraryDependencyResolver;
|
||||
|
||||
/**
|
||||
* The mocked library discovery service.
|
||||
*
|
||||
* @var \Drupal\Core\Asset\LibraryDiscoveryInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $libraryDiscovery;
|
||||
|
||||
/**
|
||||
* The mocked module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* Test library data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $libraryData = array(
|
||||
'no_deps_a' => ['js' => [], 'css' => []],
|
||||
'no_deps_b' => ['js' => [], 'css' => []],
|
||||
'no_deps_c' => ['js' => [], 'css' => []],
|
||||
'deps_a' => ['js' => [], 'css' => [], 'dependencies' => ['test/no_deps_a']],
|
||||
'deps_b' => ['js' => [], 'css' => [], 'dependencies' => ['test/no_deps_a', 'test/no_deps_b']],
|
||||
'deps_c' => ['js' => [], 'css' => [], 'dependencies' => ['test/no_deps_b', 'test/no_deps_a']],
|
||||
'nested_deps_a' => ['js' => [], 'css' => [], 'dependencies' => ['test/deps_a']],
|
||||
'nested_deps_b' => ['js' => [], 'css' => [], 'dependencies' => ['test/nested_deps_a']],
|
||||
'nested_deps_c' => ['js' => [], 'css' => [], 'dependencies' => ['test/nested_deps_b']],
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->libraryDiscovery = $this->getMockBuilder('Drupal\Core\Asset\LibraryDiscovery')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['getLibrariesByExtension'])
|
||||
->getMock();
|
||||
$this->libraryDiscovery->expects($this->any())
|
||||
->method('getLibrariesByExtension')
|
||||
->with('test')
|
||||
->will($this->returnValue($this->libraryData));
|
||||
$this->libraryDependencyResolver= new LibraryDependencyResolver($this->libraryDiscovery);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides test data for ::testGetLibrariesWithDependencies().
|
||||
*/
|
||||
public function providerTestGetLibrariesWithDependencies() {
|
||||
return [
|
||||
// Empty list of libraries.
|
||||
[[], []],
|
||||
// Without dependencies.
|
||||
[['test/no_deps_a'], ['test/no_deps_a']],
|
||||
[['test/no_deps_a', 'test/no_deps_b'], ['test/no_deps_a', 'test/no_deps_b']],
|
||||
[['test/no_deps_b', 'test/no_deps_a'], ['test/no_deps_b', 'test/no_deps_a']],
|
||||
// Single-level (direct) dependencies.
|
||||
[['test/deps_a'], ['test/no_deps_a', 'test/deps_a']],
|
||||
[['test/deps_b'], ['test/no_deps_a', 'test/no_deps_b', 'test/deps_b']],
|
||||
[['test/deps_c'], ['test/no_deps_b', 'test/no_deps_a', 'test/deps_c']],
|
||||
[['test/deps_a', 'test/deps_b'], ['test/no_deps_a', 'test/deps_a', 'test/no_deps_b', 'test/deps_b']],
|
||||
[['test/deps_a', 'test/deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/no_deps_b', 'test/deps_c']],
|
||||
[['test/deps_a', 'test/deps_b', 'test/deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/no_deps_b', 'test/deps_b', 'test/deps_c']],
|
||||
[['test/deps_b', 'test/deps_a'], ['test/no_deps_a', 'test/no_deps_b', 'test/deps_b', 'test/deps_a']],
|
||||
[['test/deps_b', 'test/deps_c'], ['test/no_deps_a', 'test/no_deps_b', 'test/deps_b', 'test/deps_c']],
|
||||
[['test/deps_c', 'test/deps_b'], ['test/no_deps_b', 'test/no_deps_a', 'test/deps_c', 'test/deps_b']],
|
||||
// Multi-level (indirect) dependencies.
|
||||
[['test/nested_deps_a'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a']],
|
||||
[['test/nested_deps_b'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b']],
|
||||
[['test/nested_deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']],
|
||||
[['test/nested_deps_a', 'test/nested_deps_b'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b']],
|
||||
[['test/nested_deps_b', 'test/nested_deps_a'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b']],
|
||||
[['test/nested_deps_a', 'test/nested_deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']],
|
||||
[['test/nested_deps_b', 'test/nested_deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']],
|
||||
[['test/nested_deps_c', 'test/nested_deps_a'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']],
|
||||
[['test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']],
|
||||
[['test/nested_deps_a', 'test/nested_deps_c', 'test/nested_deps_b'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']],
|
||||
[['test/nested_deps_b', 'test/nested_deps_a', 'test/nested_deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']],
|
||||
[['test/nested_deps_b', 'test/nested_deps_c', 'test/nested_deps_a'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']],
|
||||
[['test/nested_deps_c', 'test/nested_deps_a', 'test/nested_deps_b'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']],
|
||||
[['test/nested_deps_c', 'test/nested_deps_b', 'test/nested_deps_a'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']],
|
||||
// Complex dependencies, combining the above, with many intersections.
|
||||
[['test/deps_c', 'test/nested_deps_b'], ['test/no_deps_b', 'test/no_deps_a', 'test/deps_c', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b']],
|
||||
[['test/no_deps_a', 'test/deps_c', 'test/nested_deps_b'], ['test/no_deps_a', 'test/no_deps_b', 'test/deps_c', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b']],
|
||||
[['test/nested_deps_b', 'test/deps_c', 'test/no_deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/no_deps_b', 'test/deps_c', 'test/no_deps_c']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getLibrariesWithDependencies
|
||||
*
|
||||
* @dataProvider providerTestGetLibrariesWithDependencies
|
||||
*/
|
||||
public function testGetLibrariesWithDependencies(array $libraries, array $expected) {
|
||||
$this->assertEquals($expected, $this->libraryDependencyResolver->getLibrariesWithDependencies($libraries));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for ::testGetMinimalRepresentativeSubset().
|
||||
*/
|
||||
public function providerTestGetMinimalRepresentativeSubset() {
|
||||
return [
|
||||
// Empty list of libraries.
|
||||
[[], []],
|
||||
// Without dependencies.
|
||||
[['test/no_deps_a'], ['test/no_deps_a']],
|
||||
[['test/no_deps_a', 'test/no_deps_b'], ['test/no_deps_a', 'test/no_deps_b']],
|
||||
[['test/no_deps_b', 'test/no_deps_a'], ['test/no_deps_b', 'test/no_deps_a']],
|
||||
// Single-level (direct) dependencies.
|
||||
[['test/deps_a'], ['test/deps_a']],
|
||||
[['test/deps_b'], ['test/deps_b']],
|
||||
[['test/deps_c'], ['test/deps_c']],
|
||||
[['test/deps_a', 'test/deps_b'], ['test/deps_a', 'test/deps_b']],
|
||||
[['test/deps_a', 'test/deps_c'], ['test/deps_a', 'test/deps_c']],
|
||||
[['test/deps_a', 'test/deps_b', 'test/deps_c'], ['test/deps_a', 'test/deps_b', 'test/deps_c']],
|
||||
[['test/deps_b', 'test/deps_a'], ['test/deps_b', 'test/deps_a']],
|
||||
[['test/deps_b', 'test/deps_c'], ['test/deps_b', 'test/deps_c']],
|
||||
[['test/deps_c', 'test/deps_b'], ['test/deps_c', 'test/deps_b']],
|
||||
// Multi-level (indirect) dependencies.
|
||||
[['test/nested_deps_a'], ['test/nested_deps_a']],
|
||||
[['test/nested_deps_b'], ['test/nested_deps_b']],
|
||||
[['test/nested_deps_c'], ['test/nested_deps_c']],
|
||||
[['test/nested_deps_a', 'test/nested_deps_b'], ['test/nested_deps_b']],
|
||||
[['test/nested_deps_b', 'test/nested_deps_a'], ['test/nested_deps_b']],
|
||||
[['test/nested_deps_a', 'test/nested_deps_c'], ['test/nested_deps_c']],
|
||||
[['test/nested_deps_b', 'test/nested_deps_c'], ['test/nested_deps_c']],
|
||||
[['test/nested_deps_c', 'test/nested_deps_a'], ['test/nested_deps_c']],
|
||||
[['test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c'], ['test/nested_deps_c']],
|
||||
[['test/nested_deps_a', 'test/nested_deps_c', 'test/nested_deps_b'], ['test/nested_deps_c']],
|
||||
[['test/nested_deps_b', 'test/nested_deps_a', 'test/nested_deps_c'], ['test/nested_deps_c']],
|
||||
[['test/nested_deps_b', 'test/nested_deps_c', 'test/nested_deps_a'], ['test/nested_deps_c']],
|
||||
[['test/nested_deps_c', 'test/nested_deps_a', 'test/nested_deps_b'], ['test/nested_deps_c']],
|
||||
[['test/nested_deps_c', 'test/nested_deps_b', 'test/nested_deps_a'], ['test/nested_deps_c']],
|
||||
// Complex dependencies, combining the above, with many intersections.
|
||||
[['test/deps_c', 'test/nested_deps_b'], ['test/deps_c', 'test/nested_deps_b']],
|
||||
[['test/no_deps_a', 'test/deps_c', 'test/nested_deps_b'], ['test/deps_c', 'test/nested_deps_b']],
|
||||
[['test/nested_deps_b', 'test/deps_c', 'test/no_deps_c'], ['test/nested_deps_b', 'test/deps_c', 'test/no_deps_c']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getMinimalRepresentativeSubset
|
||||
*
|
||||
* @dataProvider providerTestGetMinimalRepresentativeSubset
|
||||
*/
|
||||
public function testGetMinimalRepresentativeSubset(array $libraries, array $expected) {
|
||||
$this->assertEquals($expected, $this->libraryDependencyResolver->getMinimalRepresentativeSubset($libraries));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Asset\LibraryDiscoveryCollectorTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Asset;
|
||||
|
||||
use Drupal\Core\Asset\LibraryDiscoveryCollector;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Asset\LibraryDiscoveryCollector
|
||||
* @group Asset
|
||||
*/
|
||||
class LibraryDiscoveryCollectorTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The mock cache backend.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* The mock lock backend.
|
||||
*
|
||||
* @var \Drupal\Core\Lock\LockBackendInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $lock;
|
||||
|
||||
/**
|
||||
* The mock library discovery parser.
|
||||
*
|
||||
* @var \Drupal\Core\Asset\LibraryDiscoveryParser|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $libraryDiscoveryParser;
|
||||
|
||||
/**
|
||||
* The library discovery collector under test.
|
||||
*
|
||||
* @var \Drupal\Core\Asset\LibraryDiscoveryCollector
|
||||
*/
|
||||
protected $libraryDiscoveryCollector;
|
||||
|
||||
/**
|
||||
* The mocked theme manager.
|
||||
*
|
||||
* @var \Drupal\Core\Theme\ThemeManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $themeManager;
|
||||
|
||||
/**
|
||||
* Test library data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $libraryData = array(
|
||||
'test_1' => array(
|
||||
'js' => array(),
|
||||
'css' => array(),
|
||||
),
|
||||
'test_2' => array(
|
||||
'js' => array(),
|
||||
'css' => array(),
|
||||
),
|
||||
);
|
||||
|
||||
protected $activeTheme;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
|
||||
$this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface');
|
||||
$this->themeManager = $this->getMockBuilder('Drupal\Core\Theme\ThemeManagerInterface')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->libraryDiscoveryParser = $this->getMockBuilder('Drupal\Core\Asset\LibraryDiscoveryParser')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the resolve cache miss function.
|
||||
*
|
||||
* @covers ::resolveCacheMiss
|
||||
*/
|
||||
public function testResolveCacheMiss() {
|
||||
$this->activeTheme = $this->getMockBuilder('Drupal\Core\Theme\ActiveTheme')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->themeManager->expects($this->once())
|
||||
->method('getActiveTheme')
|
||||
->willReturn($this->activeTheme);
|
||||
$this->activeTheme->expects($this->once())
|
||||
->method('getName')
|
||||
->willReturn('kitten_theme');
|
||||
$this->libraryDiscoveryCollector = new LibraryDiscoveryCollector($this->cache, $this->lock, $this->libraryDiscoveryParser, $this->themeManager);
|
||||
|
||||
$this->libraryDiscoveryParser->expects($this->once())
|
||||
->method('buildByExtension')
|
||||
->with('test')
|
||||
->willReturn($this->libraryData);
|
||||
|
||||
$this->assertSame($this->libraryData, $this->libraryDiscoveryCollector->get('test'));
|
||||
$this->assertSame($this->libraryData, $this->libraryDiscoveryCollector->get('test'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the destruct method.
|
||||
*
|
||||
* @covers ::destruct
|
||||
*/
|
||||
public function testDestruct() {
|
||||
$this->activeTheme = $this->getMockBuilder('Drupal\Core\Theme\ActiveTheme')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->themeManager->expects($this->once())
|
||||
->method('getActiveTheme')
|
||||
->willReturn($this->activeTheme);
|
||||
$this->activeTheme->expects($this->once())
|
||||
->method('getName')
|
||||
->willReturn('kitten_theme');
|
||||
$this->libraryDiscoveryCollector = new LibraryDiscoveryCollector($this->cache, $this->lock, $this->libraryDiscoveryParser, $this->themeManager);
|
||||
|
||||
$this->libraryDiscoveryParser->expects($this->once())
|
||||
->method('buildByExtension')
|
||||
->with('test')
|
||||
->willReturn($this->libraryData);
|
||||
|
||||
$lock_key = 'library_info:kitten_theme:Drupal\Core\Cache\CacheCollector';
|
||||
|
||||
$this->lock->expects($this->once())
|
||||
->method('acquire')
|
||||
->with($lock_key)
|
||||
->will($this->returnValue(TRUE));
|
||||
$this->cache->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->with('library_info:kitten_theme')
|
||||
->willReturn(FALSE);
|
||||
$this->cache->expects($this->once())
|
||||
->method('set')
|
||||
->with('library_info:kitten_theme', array('test' => $this->libraryData), Cache::PERMANENT, ['library_info']);
|
||||
$this->lock->expects($this->once())
|
||||
->method('release')
|
||||
->with($lock_key);
|
||||
|
||||
// This should get data and persist the key.
|
||||
$this->libraryDiscoveryCollector->get('test');
|
||||
$this->libraryDiscoveryCollector->destruct();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,568 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Asset\LibraryDiscoveryParserTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Asset;
|
||||
|
||||
use Drupal\Core\Asset\LibraryDiscoveryParser;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
if (!defined('CSS_AGGREGATE_DEFAULT')) {
|
||||
define('CSS_AGGREGATE_DEFAULT', 0);
|
||||
define('CSS_AGGREGATE_THEME', 100);
|
||||
define('CSS_BASE', -200);
|
||||
define('CSS_LAYOUT', -100);
|
||||
define('CSS_COMPONENT', 0);
|
||||
define('CSS_STATE', 100);
|
||||
define('CSS_THEME', 200);
|
||||
define('JS_SETTING', -200);
|
||||
define('JS_LIBRARY', -100);
|
||||
define('JS_DEFAULT', 0);
|
||||
define('JS_THEME', 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Asset\LibraryDiscoveryParser
|
||||
* @group Asset
|
||||
*/
|
||||
class LibraryDiscoveryParserTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The tested library discovery parser service.
|
||||
*
|
||||
* @var \Drupal\Core\Asset\LibraryDiscoveryParser|\Drupal\Tests\Core\Asset\TestLibraryDiscoveryParser
|
||||
*/
|
||||
protected $libraryDiscoveryParser;
|
||||
|
||||
/**
|
||||
* The mocked cache backend.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* The mocked module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The mocked theme manager.
|
||||
*
|
||||
* @var \Drupal\Core\Theme\ThemeManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $themeManager;
|
||||
|
||||
/**
|
||||
* The mocked lock backend.
|
||||
*
|
||||
* @var \Drupal\Core\Lock\LockBackendInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $lock;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
|
||||
$this->themeManager = $this->getMock('Drupal\Core\Theme\ThemeManagerInterface');
|
||||
$this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that basic functionality works for getLibraryByName.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testBuildByExtensionSimple() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('example_module')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'example_module', $path);
|
||||
|
||||
$libraries = $this->libraryDiscoveryParser->buildByExtension('example_module', 'example');
|
||||
$library = $libraries['example'];
|
||||
|
||||
$this->assertCount(0, $library['js']);
|
||||
$this->assertCount(1, $library['css']);
|
||||
$this->assertCount(0, $library['dependencies']);
|
||||
$this->assertEquals($path . '/css/example.css', $library['css'][0]['data']);
|
||||
|
||||
// Ensures that VERSION is replaced by the current core version.
|
||||
$this->assertEquals(\Drupal::VERSION, $library['version']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a theme can be used instead of a module.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testBuildByExtensionWithTheme() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('example_theme')
|
||||
->will($this->returnValue(FALSE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('theme', 'example_theme', $path);
|
||||
|
||||
$libraries = $this->libraryDiscoveryParser->buildByExtension('example_theme');
|
||||
$library = $libraries['example'];
|
||||
|
||||
$this->assertCount(0, $library['js']);
|
||||
$this->assertCount(1, $library['css']);
|
||||
$this->assertCount(0, $library['dependencies']);
|
||||
$this->assertEquals($path . '/css/example.css', $library['css'][0]['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a module with a missing library file results in FALSE.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testBuildByExtensionWithMissingLibraryFile() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('example_module')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files_not_existing';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'example_module', $path);
|
||||
|
||||
$this->assertSame($this->libraryDiscoveryParser->buildByExtension('example_module'), array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that an exception is thrown when a libraries file couldn't be parsed.
|
||||
*
|
||||
* @expectedException \Drupal\Core\Asset\Exception\InvalidLibraryFileException
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testInvalidLibrariesFile() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('invalid_file')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'invalid_file', $path);
|
||||
|
||||
$this->libraryDiscoveryParser->buildByExtension('invalid_file');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that an exception is thrown when no CSS/JS/setting is specified.
|
||||
*
|
||||
* @expectedException \Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException
|
||||
* @expectedExceptionMessage Incomplete library definition for definition 'example' in extension 'example_module_missing_information'
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testBuildByExtensionWithMissingInformation() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('example_module_missing_information')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'example_module_missing_information', $path);
|
||||
|
||||
$this->libraryDiscoveryParser->buildByExtension('example_module_missing_information');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the version property, and how it propagates to the contained assets.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testVersion() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('versions')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'versions', $path);
|
||||
|
||||
$libraries = $this->libraryDiscoveryParser->buildByExtension('versions');
|
||||
|
||||
$this->assertFalse(array_key_exists('version', $libraries['versionless']));
|
||||
$this->assertEquals(-1, $libraries['versionless']['css'][0]['version']);
|
||||
$this->assertEquals(-1, $libraries['versionless']['js'][0]['version']);
|
||||
|
||||
$this->assertEquals('9.8.7.6', $libraries['versioned']['version']);
|
||||
$this->assertEquals('9.8.7.6', $libraries['versioned']['css'][0]['version']);
|
||||
$this->assertEquals('9.8.7.6', $libraries['versioned']['js'][0]['version']);
|
||||
|
||||
$this->assertEquals(\Drupal::VERSION, $libraries['core-versioned']['version']);
|
||||
$this->assertEquals(\Drupal::VERSION, $libraries['core-versioned']['css'][0]['version']);
|
||||
$this->assertEquals(\Drupal::VERSION, $libraries['core-versioned']['js'][0]['version']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the version property with ISO dates.
|
||||
*
|
||||
* We want to make sure that versions defined in the YAML file are the same
|
||||
* versions that are parsed.
|
||||
*
|
||||
* For example, ISO dates are converted into UNIX time by the YAML parser.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testNonStringVersion() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('versions')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'versions', $path);
|
||||
|
||||
$libraries = $this->libraryDiscoveryParser->buildByExtension('versions');
|
||||
|
||||
// As an example, we defined an ISO date in the YAML file and the YAML
|
||||
// parser converts it into a UNIX timestamp.
|
||||
$this->assertNotEquals('2014-12-13', $libraries['invalid-version']['version']);
|
||||
// An example of an ISO date as a string which parses correctly.
|
||||
$this->assertEquals('2014-12-13', $libraries['valid-version']['version']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the version property of external libraries is handled.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testExternalLibraries() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('external')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'external', $path);
|
||||
|
||||
$libraries = $this->libraryDiscoveryParser->buildByExtension('external');
|
||||
$library = $libraries['example_external'];
|
||||
|
||||
$this->assertEquals('http://example.com/css/example_external.css', $library['css'][0]['data']);
|
||||
$this->assertEquals('http://example.com/example_external.js', $library['js'][0]['data']);
|
||||
$this->assertEquals('3.14', $library['version']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that CSS weights are taken into account properly.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testDefaultCssWeights() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('css_weights')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'css_weights', $path);
|
||||
|
||||
$libraries = $this->libraryDiscoveryParser->buildByExtension('css_weights');
|
||||
$library = $libraries['example'];
|
||||
$css = $library['css'];
|
||||
$this->assertCount(10, $css);
|
||||
|
||||
// The following default weights are tested:
|
||||
// - CSS_BASE: -200
|
||||
// - CSS_LAYOUT: -100
|
||||
// - CSS_COMPONENT: 0
|
||||
// - CSS_STATE: 100
|
||||
// - CSS_THEME: 200
|
||||
$this->assertEquals(200, $css[0]['weight']);
|
||||
$this->assertEquals(200 + 29, $css[1]['weight']);
|
||||
$this->assertEquals(-200, $css[2]['weight']);
|
||||
$this->assertEquals(-200 + 97, $css[3]['weight']);
|
||||
$this->assertEquals(-100, $css[4]['weight']);
|
||||
$this->assertEquals(-100 + 92, $css[5]['weight']);
|
||||
$this->assertEquals(0, $css[6]['weight']);
|
||||
$this->assertEquals(45, $css[7]['weight']);
|
||||
$this->assertEquals(100, $css[8]['weight']);
|
||||
$this->assertEquals(100 + 8, $css[9]['weight']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that you cannot provide positive weights for JavaScript libraries.
|
||||
*
|
||||
* @expectedException \UnexpectedValueException
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testJsWithPositiveWeight() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('js_positive_weight')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'js_positive_weight', $path);
|
||||
|
||||
$this->libraryDiscoveryParser->buildByExtension('js_positive_weight');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a library with CSS/JavaScript and a setting.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testLibraryWithCssJsSetting() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('css_js_settings')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'css_js_settings', $path);
|
||||
|
||||
$libraries = $this->libraryDiscoveryParser->buildByExtension('css_js_settings');
|
||||
$library = $libraries['example'];
|
||||
|
||||
// Ensures that the group and type are set automatically.
|
||||
$this->assertEquals(-100, $library['js'][0]['group']);
|
||||
$this->assertEquals('file', $library['js'][0]['type']);
|
||||
$this->assertEquals($path . '/js/example.js', $library['js'][0]['data']);
|
||||
|
||||
$this->assertEquals(0, $library['css'][0]['group']);
|
||||
$this->assertEquals('file', $library['css'][0]['type']);
|
||||
$this->assertEquals($path . '/css/base.css', $library['css'][0]['data']);
|
||||
|
||||
$this->assertEquals(array('key' => 'value'), $library['drupalSettings']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a library with dependencies.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testLibraryWithDependencies() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('dependencies')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'dependencies', $path);
|
||||
|
||||
$libraries = $this->libraryDiscoveryParser->buildByExtension('dependencies');
|
||||
$library = $libraries['example'];
|
||||
|
||||
$this->assertCount(2, $library['dependencies']);
|
||||
$this->assertEquals('external/example_external', $library['dependencies'][0]);
|
||||
$this->assertEquals('example_module/example', $library['dependencies'][1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a library with a couple of data formats like full URL.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testLibraryWithDataTypes() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('data_types')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'data_types', $path);
|
||||
|
||||
$this->libraryDiscoveryParser->setFileValidUri('public://test.css', TRUE);
|
||||
$this->libraryDiscoveryParser->setFileValidUri('public://test2.css', FALSE);
|
||||
|
||||
$libraries = $this->libraryDiscoveryParser->buildByExtension('data_types');
|
||||
$library = $libraries['example'];
|
||||
|
||||
$this->assertCount(5, $library['css']);
|
||||
$this->assertEquals('external', $library['css'][0]['type']);
|
||||
$this->assertEquals('http://example.com/test.css', $library['css'][0]['data']);
|
||||
$this->assertEquals('file', $library['css'][1]['type']);
|
||||
$this->assertEquals('tmp/test.css', $library['css'][1]['data']);
|
||||
$this->assertEquals('external', $library['css'][2]['type']);
|
||||
$this->assertEquals('//cdn.com/test.css', $library['css'][2]['data']);
|
||||
$this->assertEquals('file', $library['css'][3]['type']);
|
||||
$this->assertEquals('public://test.css', $library['css'][3]['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a library with JavaScript-specific flags.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testLibraryWithJavaScript() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('js')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'js', $path);
|
||||
|
||||
$libraries = $this->libraryDiscoveryParser->buildByExtension('js');
|
||||
$library = $libraries['example'];
|
||||
|
||||
$this->assertCount(2, $library['js']);
|
||||
$this->assertEquals(FALSE, $library['js'][0]['minified']);
|
||||
$this->assertEquals(TRUE, $library['js'][1]['minified']);
|
||||
}
|
||||
/**
|
||||
* Tests that an exception is thrown when license is missing when 3rd party.
|
||||
*
|
||||
* @expectedException \Drupal\Core\Asset\Exception\LibraryDefinitionMissingLicenseException
|
||||
* @expectedExceptionMessage Missing license information in library definition for definition 'no-license-info-but-remote' extension 'licenses_missing_information': it has a remote, but no license.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testLibraryThirdPartyWithMissingLicense() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('licenses_missing_information')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'licenses_missing_information', $path);
|
||||
|
||||
$this->libraryDiscoveryParser->buildByExtension('licenses_missing_information');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a library with various licenses, some GPL-compatible, some not.
|
||||
*
|
||||
* @covers ::buildByExtension
|
||||
*/
|
||||
public function testLibraryWithLicenses() {
|
||||
$this->moduleHandler->expects($this->atLeastOnce())
|
||||
->method('moduleExists')
|
||||
->with('licenses')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$path = __DIR__ . '/library_test_files';
|
||||
$path = substr($path, strlen($this->root) + 1);
|
||||
$this->libraryDiscoveryParser->setPaths('module', 'licenses', $path);
|
||||
|
||||
$libraries = $this->libraryDiscoveryParser->buildByExtension('licenses');
|
||||
|
||||
// For libraries without license info, the default license is applied.
|
||||
$library = $libraries['no-license-info'];
|
||||
$this->assertCount(1, $library['css']);
|
||||
$this->assertCount(1, $library['js']);
|
||||
$this->assertTrue(isset($library['license']));
|
||||
$default_license = array(
|
||||
'name' => 'GNU-GPL-2.0-or-later',
|
||||
'url' => 'https://www.drupal.org/licensing/faq',
|
||||
'gpl-compatible' => TRUE,
|
||||
);
|
||||
$this->assertEquals($library['license'], $default_license);
|
||||
|
||||
// GPL2-licensed libraries.
|
||||
$library = $libraries['gpl2'];
|
||||
$this->assertCount(1, $library['css']);
|
||||
$this->assertCount(1, $library['js']);
|
||||
$expected_license = array(
|
||||
'name' => 'gpl2',
|
||||
'url' => 'https://url-to-gpl2-license',
|
||||
'gpl-compatible' => TRUE,
|
||||
);
|
||||
$this->assertEquals($library['license'], $expected_license);
|
||||
|
||||
// MIT-licensed libraries.
|
||||
$library = $libraries['mit'];
|
||||
$this->assertCount(1, $library['css']);
|
||||
$this->assertCount(1, $library['js']);
|
||||
$expected_license = array(
|
||||
'name' => 'MIT',
|
||||
'url' => 'https://url-to-mit-license',
|
||||
'gpl-compatible' => TRUE,
|
||||
);
|
||||
$this->assertEquals($library['license'], $expected_license);
|
||||
|
||||
// Libraries in the Public Domain.
|
||||
$library = $libraries['public-domain'];
|
||||
$this->assertCount(1, $library['css']);
|
||||
$this->assertCount(1, $library['js']);
|
||||
$expected_license = array(
|
||||
'name' => 'Public Domain',
|
||||
'url' => 'https://url-to-public-domain-license',
|
||||
'gpl-compatible' => TRUE,
|
||||
);
|
||||
$this->assertEquals($library['license'], $expected_license);
|
||||
|
||||
// Apache-licensed libraries.
|
||||
$library = $libraries['apache'];
|
||||
$this->assertCount(1, $library['css']);
|
||||
$this->assertCount(1, $library['js']);
|
||||
$expected_license = array(
|
||||
'name' => 'apache',
|
||||
'url' => 'https://url-to-apache-license',
|
||||
'gpl-compatible' => FALSE,
|
||||
);
|
||||
$this->assertEquals($library['license'], $expected_license);
|
||||
|
||||
// Copyrighted libraries.
|
||||
$library = $libraries['copyright'];
|
||||
$this->assertCount(1, $library['css']);
|
||||
$this->assertCount(1, $library['js']);
|
||||
$expected_license = array(
|
||||
'name' => '© Some company',
|
||||
'gpl-compatible' => FALSE,
|
||||
);
|
||||
$this->assertEquals($library['license'], $expected_license);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the tested class to mock the external dependencies.
|
||||
*/
|
||||
class TestLibraryDiscoveryParser extends LibraryDiscoveryParser {
|
||||
|
||||
protected $paths;
|
||||
|
||||
protected $validUris;
|
||||
|
||||
protected function drupalGetPath($type, $name) {
|
||||
return isset($this->paths[$type][$name]) ? $this->paths[$type][$name] : NULL;
|
||||
}
|
||||
|
||||
public function setPaths($type, $name, $path) {
|
||||
$this->paths[$type][$name] = $path;
|
||||
}
|
||||
|
||||
protected function fileValidUri($source) {
|
||||
return isset($this->validUris[$source]) ? $this->validUris[$source] : FALSE;
|
||||
}
|
||||
|
||||
public function setFileValidUri($source, $valid) {
|
||||
$this->validUris[$source] = $valid;
|
||||
}
|
||||
|
||||
}
|
92
core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryTest.php
Normal file
92
core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryTest.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Asset\LibraryDiscoveryTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Asset;
|
||||
|
||||
use Drupal\Core\Asset\LibraryDiscovery;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Asset\LibraryDiscovery
|
||||
* @group Asset
|
||||
*/
|
||||
class LibraryDiscoveryTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The tested library discovery service.
|
||||
*
|
||||
* @var \Drupal\Core\Asset\LibraryDiscovery
|
||||
*/
|
||||
protected $libraryDiscovery;
|
||||
|
||||
/**
|
||||
* The mocked library discovery cache collector.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheCollectorInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $libraryDiscoveryCollector;
|
||||
|
||||
/**
|
||||
* The cache tags invalidator.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $cacheTagsInvalidator;
|
||||
|
||||
/**
|
||||
* Test library data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $libraryData = [
|
||||
'test_1' => [
|
||||
'js' => [],
|
||||
'css' => [
|
||||
'foo.css' => [],
|
||||
],
|
||||
],
|
||||
'test_2' => [
|
||||
'js' => [
|
||||
'bar.js' => [],
|
||||
],
|
||||
'css' => [],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
|
||||
$this->libraryDiscoveryCollector = $this->getMockBuilder('Drupal\Core\Asset\LibraryDiscoveryCollector')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->libraryDiscovery = new LibraryDiscovery($this->libraryDiscoveryCollector, $this->cacheTagsInvalidator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getLibrariesByExtension
|
||||
*/
|
||||
public function testGetLibrariesByExtension() {
|
||||
$this->libraryDiscoveryCollector->expects($this->once())
|
||||
->method('get')
|
||||
->with('test')
|
||||
->willReturn($this->libraryData);
|
||||
|
||||
$this->libraryDiscovery->getLibrariesbyExtension('test');
|
||||
// Verify that subsequent calls don't trigger hook_library_info_alter()
|
||||
// and hook_js_settings_alter() invocations, nor do they talk to the
|
||||
// collector again. This ensures that the alterations made by
|
||||
// hook_library_info_alter() and hook_js_settings_alter() implementations
|
||||
// are statically cached, as desired.
|
||||
$this->libraryDiscovery->getLibraryByName('test', 'test_1');
|
||||
$this->libraryDiscovery->getLibrariesbyExtension('test');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
@charset "UTF-8";html{font-family:"sans-serif";}
|
|
@ -0,0 +1 @@
|
|||
html{font-family:"sans-serif";}
|
|
@ -0,0 +1,2 @@
|
|||
@charset "UTF-8";
|
||||
html{font-family:"sans-serif";}
|
|
@ -0,0 +1 @@
|
|||
@charset "UTF-8";html{font-family:"sans-serif";}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
.test1{display:block;}html .clear-block{height:1%;}.clear-block{display:block;font:italic bold 12px/30px Georgia,serif;}.test2{display:block;}.bkslshv1{background-color:#c00;}.test3{display:block;}.test4{display:block;}.comment-in-double-quotes:before{content:"/* ";}.this_rule_must_stay{color:#f00;background-color:#fff;}.comment-in-double-quotes:after{content:" */";}.comment-in-single-quotes:before{content:'/*';}.this_rule_must_stay{color:#f00;background-color:#fff;}.comment-in-single-quotes:after{content:'*/';}.comment-in-mixed-quotes:before{content:'"/*"';}.this_rule_must_stay{color:#f00;background-color:#fff;}.comment-in-mixed-quotes:after{content:"'*/'";}.comment-in-quotes-with-escaped:before{content:'/* \" \' */';}.this_rule_must_stay{color:#f00;background-color:#fff;}.comment-in-quotes-with-escaped:after{content:"*/ \" \ '";}
|
|
@ -0,0 +1,3 @@
|
|||
.byte-order-mark-test {
|
||||
content: "☃";
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
@charset "utf-8";
|
||||
.byte-order-mark-charset-test {
|
||||
content: "☃";
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
@charset "iso-8859-15";
|
||||
.charset-test {
|
||||
content: "¤";
|
||||
}
|
32
core/tests/Drupal/Tests/Core/Asset/css_test_files/css_input_with_import.css
vendored
Normal file
32
core/tests/Drupal/Tests/Core/Asset/css_test_files/css_input_with_import.css
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
|
||||
|
||||
@import "import1.css";
|
||||
@import "import2.css";
|
||||
@import url("http://example.com/style.css");
|
||||
@import url("//example.com/style.css");
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #edf5fa;
|
||||
font: 76%/170% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
||||
|
||||
.this .is .a .test {
|
||||
font: 1em/100% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
||||
.this
|
||||
.is
|
||||
.a
|
||||
.test {
|
||||
font: 1em/100% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
||||
|
||||
textarea, select {
|
||||
font: 1em/160% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
ul,select{font:1em/160% Verdana,sans-serif;color:#494949;}.ui-icon{background-image:url(images/icon.png);}.data .double-quote{background-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");}.data .single-quote{background-image:url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AKAAH//Z');}.data .no-quote{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAEAQAAAAAo/mtHAAAAIElEQVQIHWMRnWHwcRNLN8NZ7QYWwT8PlBlYsgqVBRsAankIMw5MtnoAAAAASUVORK5CYII=);}
|
||||
p,select{font:1em/160% Verdana,sans-serif;color:#494949;}
|
||||
@import url("http://example.com/style.css");@import url("//example.com/style.css");body{margin:0;padding:0;background:#edf5fa;font:76%/170% Verdana,sans-serif;color:#494949;}.this .is .a .test{font:1em/100% Verdana,sans-serif;color:#494949;}.this
|
||||
.is
|
||||
.a
|
||||
.test{font:1em/100% Verdana,sans-serif;color:#494949;}textarea,select{font:1em/160% Verdana,sans-serif;color:#494949;}
|
Binary file not shown.
65
core/tests/Drupal/Tests/Core/Asset/css_test_files/css_input_without_import.css
vendored
Normal file
65
core/tests/Drupal/Tests/Core/Asset/css_test_files/css_input_without_import.css
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
|
||||
/**
|
||||
* @file Basic css that does not use import
|
||||
*/
|
||||
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #edf5fa;
|
||||
font: 76%/170% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
||||
|
||||
.this .is .a .test {
|
||||
font: 1em/100% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
||||
|
||||
/**
|
||||
* CSS spec says that all whitespace is valid whitespace, so this selector
|
||||
* should be just as good as the one above.
|
||||
*/
|
||||
.this
|
||||
.is
|
||||
.a
|
||||
.test {
|
||||
font: 1em/100% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
||||
|
||||
some :pseudo .thing {
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
::-moz-selection {
|
||||
background: #000;
|
||||
color:#fff;
|
||||
|
||||
}
|
||||
::selection {
|
||||
background: #000;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@media print {
|
||||
* {
|
||||
background: #000 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
@page {
|
||||
margin: 0.5cm;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-device-width: 480px) {
|
||||
background: #000;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
textarea, select {
|
||||
font: 1em/160% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
body{margin:0;padding:0;background:#edf5fa;font:76%/170% Verdana,sans-serif;color:#494949;}.this .is .a .test{font:1em/100% Verdana,sans-serif;color:#494949;}.this
|
||||
.is
|
||||
.a
|
||||
.test{font:1em/100% Verdana,sans-serif;color:#494949;}some :pseudo .thing{border-radius:3px;}::-moz-selection{background:#000;color:#fff;}::selection{background:#000;color:#fff;}@media print{*{background:#000 !important;color:#fff !important;}@page{margin:0.5cm;}}@media screen and (max-device-width:480px){background:#000;color:#fff;}textarea,select{font:1em/160% Verdana,sans-serif;color:#494949;}
|
29
core/tests/Drupal/Tests/Core/Asset/css_test_files/css_subfolder/css_input_with_import.css
vendored
Normal file
29
core/tests/Drupal/Tests/Core/Asset/css_test_files/css_subfolder/css_input_with_import.css
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
|
||||
|
||||
@import "../import1.css";
|
||||
@import "../import2.css";
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #edf5fa;
|
||||
font: 76%/170% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
||||
|
||||
.this .is .a .test {
|
||||
font: 1em/100% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
||||
.this
|
||||
.is
|
||||
.a
|
||||
.test {
|
||||
font: 1em/100% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
||||
|
||||
textarea, select {
|
||||
font: 1em/160% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
ul,select{font:1em/160% Verdana,sans-serif;color:#494949;}.ui-icon{background-image:url(../images/icon.png);}.data .double-quote{background-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");}.data .single-quote{background-image:url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AKAAH//Z');}.data .no-quote{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAEAQAAAAAo/mtHAAAAIElEQVQIHWMRnWHwcRNLN8NZ7QYWwT8PlBlYsgqVBRsAankIMw5MtnoAAAAASUVORK5CYII=);}
|
||||
p,select{font:1em/160% Verdana,sans-serif;color:#494949;}
|
||||
body{margin:0;padding:0;background:#edf5fa;font:76%/170% Verdana,sans-serif;color:#494949;}.this .is .a .test{font:1em/100% Verdana,sans-serif;color:#494949;}.this
|
||||
.is
|
||||
.a
|
||||
.test{font:1em/100% Verdana,sans-serif;color:#494949;}textarea,select{font:1em/160% Verdana,sans-serif;color:#494949;}
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
ul, select {
|
||||
font: 1em/160% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
||||
.ui-icon{background-image: url(images/icon.png);}
|
||||
|
||||
/* Test data URI images with different quote styles. */
|
||||
.data .double-quote {
|
||||
/* http://stackoverflow.com/a/13139830/11023 */
|
||||
background-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
|
||||
}
|
||||
|
||||
.data .single-quote {
|
||||
background-image: url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AKAAH//Z');
|
||||
}
|
||||
|
||||
.data .no-quote {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAEAQAAAAAo/mtHAAAAIElEQVQIHWMRnWHwcRNLN8NZ7QYWwT8PlBlYsgqVBRsAankIMw5MtnoAAAAASUVORK5CYII=);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
p, select {
|
||||
font: 1em/160% Verdana, sans-serif;
|
||||
color: #494949;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
var latin9Char = '¤';
|
|
@ -0,0 +1 @@
|
|||
var latin9Char = '€';
|
2
core/tests/Drupal/Tests/Core/Asset/js_test_files/source_mapping_url.min.js
vendored
Normal file
2
core/tests/Drupal/Tests/Core/Asset/js_test_files/source_mapping_url.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
(function($) { "use strict"; })
|
||||
//# sourceMappingURL=source_mapping_url.min.map
|
|
@ -0,0 +1 @@
|
|||
(function($) { "use strict"; })
|
2
core/tests/Drupal/Tests/Core/Asset/js_test_files/source_mapping_url_old.min.js
vendored
Normal file
2
core/tests/Drupal/Tests/Core/Asset/js_test_files/source_mapping_url_old.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
(function($) { "use strict"; })
|
||||
//@ sourceMappingURL=source_mapping_url.min.map
|
|
@ -0,0 +1 @@
|
|||
(function($) { "use strict"; })
|
2
core/tests/Drupal/Tests/Core/Asset/js_test_files/source_url.min.js
vendored
Normal file
2
core/tests/Drupal/Tests/Core/Asset/js_test_files/source_url.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
(function($) { "use strict"; })
|
||||
//# sourceURL=source_mapping_url.js
|
|
@ -0,0 +1 @@
|
|||
(function($) { "use strict"; })
|
2
core/tests/Drupal/Tests/Core/Asset/js_test_files/source_url_old.min.js
vendored
Normal file
2
core/tests/Drupal/Tests/Core/Asset/js_test_files/source_url_old.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
(function($) { "use strict"; })
|
||||
//@ sourceURL=source_mapping_url.js
|
|
@ -0,0 +1 @@
|
|||
(function($) { "use strict"; })
|
BIN
core/tests/Drupal/Tests/Core/Asset/js_test_files/utf16_bom.js
Normal file
BIN
core/tests/Drupal/Tests/Core/Asset/js_test_files/utf16_bom.js
Normal file
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
var utf8BOM = '☃';
|
|
@ -0,0 +1 @@
|
|||
var utf8BOM = '☃';
|
|
@ -0,0 +1 @@
|
|||
var utf8BOM = '☃';
|
|
@ -0,0 +1,8 @@
|
|||
example:
|
||||
css:
|
||||
base:
|
||||
css/base.css: {}
|
||||
js:
|
||||
js/example.js: {}
|
||||
drupalSettings:
|
||||
key: value
|
|
@ -0,0 +1,22 @@
|
|||
example:
|
||||
css:
|
||||
theme:
|
||||
css/theme__no_weight.css: {}
|
||||
css/theme__weight.css:
|
||||
weight: 29
|
||||
base:
|
||||
css/base__no_weight.css: {}
|
||||
css/base__weight.css:
|
||||
weight: 97
|
||||
layout:
|
||||
css/layout__no_weight.css: {}
|
||||
css/layout__weight.css:
|
||||
weight: 92
|
||||
component:
|
||||
css/component__no_weight.css: {}
|
||||
css/component__weight.css:
|
||||
weight: 45
|
||||
state:
|
||||
css/state__no_weight.css: {}
|
||||
css/state__weight.css:
|
||||
weight: 8
|
|
@ -0,0 +1,13 @@
|
|||
example:
|
||||
css:
|
||||
theme:
|
||||
# External URL.
|
||||
'http://example.com/test.css':
|
||||
type: external
|
||||
# Absolute path.
|
||||
/tmp/test.css: {}
|
||||
# Protocol free.
|
||||
//cdn.com/test.css: {}
|
||||
# Stream wrapper URI.
|
||||
'public://test.css': {}
|
||||
'example://test2.css': {}
|
|
@ -0,0 +1,6 @@
|
|||
example:
|
||||
css:
|
||||
css/example.js: {}
|
||||
dependencies:
|
||||
- external/example_external
|
||||
- example_module/example
|
|
@ -0,0 +1,5 @@
|
|||
example:
|
||||
version: VERSION
|
||||
css:
|
||||
theme:
|
||||
css/example.css: {}
|
|
@ -0,0 +1,2 @@
|
|||
example:
|
||||
version: VERSION
|
|
@ -0,0 +1,4 @@
|
|||
example:
|
||||
css:
|
||||
theme:
|
||||
css/example.css: {}
|
|
@ -0,0 +1,7 @@
|
|||
example_external:
|
||||
version: v3.14
|
||||
js:
|
||||
http://example.com/example_external.js: { type: external }
|
||||
css:
|
||||
theme:
|
||||
http://example.com/css/example_external.css: { type: external }
|
|
@ -0,0 +1,3 @@
|
|||
example:
|
||||
key1: value1
|
||||
key2: value2
|
|
@ -0,0 +1,4 @@
|
|||
example:
|
||||
js:
|
||||
js/unminified.js: {}
|
||||
js/minified.js: { minified: true }
|
|
@ -0,0 +1,4 @@
|
|||
example:
|
||||
js:
|
||||
js/positive_weight.js:
|
||||
weight: 10
|
|
@ -0,0 +1,72 @@
|
|||
# No license information: should default to GPL 2.0 or later..
|
||||
no-license-info:
|
||||
version: 1.0
|
||||
js:
|
||||
no-license-info.js: {}
|
||||
css:
|
||||
base:
|
||||
no-license-info.css: {}
|
||||
|
||||
# A library with all assets licensed under the GPL-compatible GPL 2 license.
|
||||
gpl2:
|
||||
version: 1.0
|
||||
license:
|
||||
name: gpl2
|
||||
url: https://url-to-gpl2-license
|
||||
gpl-compatible: true
|
||||
js:
|
||||
gpl2.js: {}
|
||||
css:
|
||||
base:
|
||||
gpl2.css: {}
|
||||
|
||||
# A library with all assets licensed under the GPL-compatible MIT license.
|
||||
mit:
|
||||
version: 1.0
|
||||
license:
|
||||
name: MIT
|
||||
url: https://url-to-mit-license
|
||||
gpl-compatible: true
|
||||
js:
|
||||
mit.js: {}
|
||||
css:
|
||||
base:
|
||||
mit.css: {}
|
||||
|
||||
# A library with all assets licensed under the GPL-compatible Public Domain.
|
||||
public-domain:
|
||||
version: 1.0
|
||||
license:
|
||||
name: Public Domain
|
||||
url: https://url-to-public-domain-license
|
||||
gpl-compatible: true
|
||||
js:
|
||||
public-domain.js: {}
|
||||
css:
|
||||
base:
|
||||
public-domain.css: {}
|
||||
|
||||
# A library with all assets licensed under the GPL-incompatible Apache license.
|
||||
apache:
|
||||
version: 1.0
|
||||
license:
|
||||
name: apache
|
||||
url: https://url-to-apache-license
|
||||
gpl-compatible: false
|
||||
js:
|
||||
apache.js: {}
|
||||
css:
|
||||
base:
|
||||
apache.css: {}
|
||||
|
||||
# A library with all assets licensed under the GPL-incompatible copyright.
|
||||
copyright:
|
||||
version: 1.0
|
||||
license:
|
||||
name: © Some company
|
||||
gpl-compatible: false
|
||||
js:
|
||||
copyright.js: {}
|
||||
css:
|
||||
base:
|
||||
copyright.css: {}
|
|
@ -0,0 +1,9 @@
|
|||
# No license information for a 3rd party library (it has the 'remote' key).
|
||||
no-license-info-but-remote:
|
||||
version: 1.0
|
||||
remote: https://url-to-remote
|
||||
js:
|
||||
no-license-info-but-remote.js: {}
|
||||
css:
|
||||
base:
|
||||
no-license-info-but-remote.css: {}
|
|
@ -0,0 +1,32 @@
|
|||
versionless:
|
||||
css:
|
||||
theme:
|
||||
versionless.css: {}
|
||||
js:
|
||||
versionless.js: {}
|
||||
|
||||
versioned:
|
||||
version: "9.8.7.6"
|
||||
css:
|
||||
theme:
|
||||
versioned.css: {}
|
||||
js:
|
||||
versioned.js: {}
|
||||
|
||||
core-versioned:
|
||||
version: VERSION
|
||||
css:
|
||||
theme:
|
||||
core-versioned.css: {}
|
||||
js:
|
||||
core-versioned.js: {}
|
||||
|
||||
invalid-version:
|
||||
version: 2014-12-13
|
||||
js:
|
||||
versioned.js: {}
|
||||
|
||||
valid-version:
|
||||
version: "2014-12-13"
|
||||
js:
|
||||
versioned.js: {}
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Authentication\AuthenticationManagerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Authentication;
|
||||
|
||||
use Drupal\Core\Authentication\AuthenticationManager;
|
||||
use Drupal\Core\Authentication\AuthenticationProviderFilterInterface;
|
||||
use Drupal\Core\Authentication\AuthenticationProviderInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Authentication\AuthenticationManager
|
||||
* @group Authentication
|
||||
*/
|
||||
class AuthenticationManagerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @covers ::defaultFilter
|
||||
* @covers ::applyFilter
|
||||
*
|
||||
* @dataProvider providerTestDefaultFilter
|
||||
*/
|
||||
public function testDefaultFilter($applies, $has_route, $auth_option, $provider_id, $global) {
|
||||
$authentication_manager = new AuthenticationManager();
|
||||
$auth_provider = $this->getMock('Drupal\Core\Authentication\AuthenticationProviderInterface');
|
||||
$authentication_manager->addProvider($auth_provider, $provider_id, 0, $global);
|
||||
|
||||
$request = new Request();
|
||||
if ($has_route) {
|
||||
$route = new Route('/example');
|
||||
if ($auth_option) {
|
||||
$route->setOption('_auth', $auth_option);
|
||||
}
|
||||
$request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, $route);
|
||||
}
|
||||
|
||||
$this->assertSame($applies, $authentication_manager->appliesToRoutedRequest($request, FALSE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::applyFilter
|
||||
*/
|
||||
public function testApplyFilterWithFilterprovider() {
|
||||
$authentication_manager = new AuthenticationManager();
|
||||
$auth_provider = $this->getMock('Drupal\Tests\Core\Authentication\TestAuthenticationProviderInterface');
|
||||
$authentication_manager->addProvider($auth_provider, 'filtered', 0);
|
||||
|
||||
$auth_provider->expects($this->once())
|
||||
->method('appliesToRoutedRequest')
|
||||
->willReturn(TRUE);
|
||||
|
||||
$request = new Request();
|
||||
$this->assertTrue($authentication_manager->appliesToRoutedRequest($request, FALSE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data to self::testDefaultFilter().
|
||||
*/
|
||||
public function providerTestDefaultFilter() {
|
||||
$data = [];
|
||||
// No route, cookie is global, should apply.
|
||||
$data[] = [TRUE, FALSE, [], 'cookie', TRUE];
|
||||
// No route, cookie is not global, should not apply.
|
||||
$data[] = [FALSE, FALSE, [], 'cookie', FALSE];
|
||||
// Route, no _auth, cookie is global, should apply.
|
||||
$data[] = [TRUE, TRUE, [], 'cookie', TRUE];
|
||||
// Route, no _auth, cookie is not global, should not apply.
|
||||
$data[] = [FALSE, TRUE, [], 'cookie', FALSE];
|
||||
// Route, with _auth and non-matching provider, should not apply.
|
||||
$data[] = [FALSE, TRUE, ['basic_auth'], 'cookie', TRUE];
|
||||
// Route, with _auth and matching provider should not apply.
|
||||
$data[] = [TRUE, TRUE, ['basic_auth'], 'basic_auth', TRUE];
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper interface to mock two interfaces at once.
|
||||
*/
|
||||
interface TestAuthenticationProviderInterface extends AuthenticationProviderFilterInterface, AuthenticationProviderInterface {}
|
88
core/tests/Drupal/Tests/Core/Batch/PercentagesTest.php
Normal file
88
core/tests/Drupal/Tests/Core/Batch/PercentagesTest.php
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Batch\PercentagesTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Batch;
|
||||
|
||||
use Drupal\Core\Batch\Percentage;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Batch\Percentage
|
||||
* @group Batch
|
||||
*
|
||||
* Tests the Batch helper object to make sure that the rounding works properly
|
||||
* in all cases.
|
||||
*/
|
||||
class PercentagesTest extends UnitTestCase {
|
||||
protected $testCases = array();
|
||||
|
||||
/**
|
||||
* @dataProvider providerTestPercentages
|
||||
* @covers ::format
|
||||
*/
|
||||
public function testPercentages($total, $current, $expected_result) {
|
||||
$actual_result = Percentage::format($total, $current);
|
||||
$this->assertEquals($actual_result, $expected_result, sprintf('The expected the batch api percentage at the state %s/%s is %s%% and got %s%%.', $current, $total, $expected_result, $actual_result));
|
||||
}
|
||||
/**
|
||||
* Provide data for batch unit tests.
|
||||
*
|
||||
* @return array
|
||||
* An array of data used by the test.
|
||||
*/
|
||||
public function providerTestPercentages() {
|
||||
// Set up an array of test cases.
|
||||
return array(
|
||||
// array(total, current, expected).
|
||||
// 1/2 is 50%.
|
||||
array(2, 1, '50'),
|
||||
// Though we should never encounter a case where the current set is set
|
||||
// 0, if we did, we should get 0%.
|
||||
array(3, 0, '0'),
|
||||
// 1/3 is closer to 33% than to 34%.
|
||||
array(3, 1, '33'),
|
||||
// 2/3 is closer to 67% than to 66%.
|
||||
array(3, 2, '67'),
|
||||
// 1/199 should round up to 1%.
|
||||
array(199, 1, '1'),
|
||||
// 198/199 should round down to 99%.
|
||||
array(199, 198, '99'),
|
||||
// 199/200 would have rounded up to 100%, which would give the false
|
||||
// impression of being finished, so we add another digit and should get
|
||||
// 99.5%.
|
||||
array(200, 199, '99.5'),
|
||||
// The same logic holds for 1/200: we should get 0.5%.
|
||||
array(200, 1, '0.5'),
|
||||
// Numbers that come out evenly, such as 50/200, should be forced to have
|
||||
// extra digits for consistency.
|
||||
array(200, 50, '25.0'),
|
||||
// Regardless of number of digits we're using, 100% should always just be
|
||||
// 100%.
|
||||
array(200, 200, '100'),
|
||||
// 1998/1999 should similarly round down to 99.9%.
|
||||
array(1999, 1998, '99.9'),
|
||||
// 1999/2000 should add another digit and go to 99.95%.
|
||||
array(2000, 1999, '99.95'),
|
||||
// 19999/20000 should add yet another digit and go to 99.995%.
|
||||
array(20000, 19999, '99.995'),
|
||||
// The next five test cases simulate a batch with a single operation
|
||||
// ('total' equals 1) that takes several steps to complete. Within the
|
||||
// operation, we imagine that there are 501 items to process, and 100 are
|
||||
// completed during each step. The percentages we get back should be
|
||||
// rounded the usual way for the first few passes (i.e., 20%, 40%, etc.),
|
||||
// but for the last pass through, when 500 out of 501 items have been
|
||||
// processed, we do not want to round up to 100%, since that would
|
||||
// erroneously indicate that the processing is complete.
|
||||
array('total' => 1, 'current' => 100/501, '20'),
|
||||
array('total' => 1, 'current' => 200/501, '40'),
|
||||
array('total' => 1, 'current' => 300/501, '60'),
|
||||
array('total' => 1, 'current' => 400/501, '80'),
|
||||
array('total' => 1, 'current' => 500/501, '99.8'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
50
core/tests/Drupal/Tests/Core/Block/BlockBaseTest.php
Normal file
50
core/tests/Drupal/Tests/Core/Block/BlockBaseTest.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Block\BlockBaseTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Block;
|
||||
|
||||
use Drupal\block_test\Plugin\Block\TestBlockInstantiation;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Block\BlockBase
|
||||
* @group block
|
||||
*/
|
||||
class BlockBaseTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests the machine name suggestion.
|
||||
*
|
||||
* @see \Drupal\Core\Block\BlockBase::getMachineNameSuggestion().
|
||||
*/
|
||||
public function testGetMachineNameSuggestion() {
|
||||
$module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
|
||||
$transliteration = $this->getMockBuilder('Drupal\Core\Transliteration\PhpTransliteration')
|
||||
->setConstructorArgs(array(NULL, $module_handler))
|
||||
->setMethods(array('readLanguageOverrides'))
|
||||
->getMock();
|
||||
|
||||
$config = array();
|
||||
$definition = array(
|
||||
'admin_label' => 'Admin label',
|
||||
'provider' => 'block_test',
|
||||
);
|
||||
$block_base = new TestBlockInstantiation($config, 'test_block_instantiation', $definition);
|
||||
$block_base->setTransliteration($transliteration);
|
||||
$this->assertEquals('adminlabel', $block_base->getMachineNameSuggestion());
|
||||
|
||||
// Test with more unicodes.
|
||||
$definition = array(
|
||||
'admin_label' => 'über åwesome',
|
||||
'provider' => 'block_test',
|
||||
);
|
||||
$block_base = new TestBlockInstantiation($config, 'test_block_instantiation', $definition);
|
||||
$block_base->setTransliteration($transliteration);
|
||||
$this->assertEquals('uberawesome', $block_base->getMachineNameSuggestion());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Breadcrumb\BreadcrumbManagerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Breadcrumb;
|
||||
|
||||
use Drupal\Core\Breadcrumb\BreadcrumbManager;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Breadcrumb\BreadcrumbManager
|
||||
* @group Breadcrumb
|
||||
*/
|
||||
class BreadcrumbManagerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The tested breadcrumb manager.
|
||||
*
|
||||
* @var \Drupal\Core\Breadcrumb\BreadcrumbManager
|
||||
*/
|
||||
protected $breadcrumbManager;
|
||||
|
||||
/**
|
||||
* The mocked module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
|
||||
$this->breadcrumbManager = new BreadcrumbManager($this->moduleHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the build method with a single breadcrumb builder.
|
||||
*/
|
||||
public function testBuildWithSingleBuilder() {
|
||||
$builder = $this->getMock('Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface');
|
||||
$breadcrumb = array('<a href="/example">Test</a>');
|
||||
|
||||
$builder->expects($this->once())
|
||||
->method('applies')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$builder->expects($this->once())
|
||||
->method('build')
|
||||
->will($this->returnValue($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));
|
||||
|
||||
$this->breadcrumbManager->addBuilder($builder, 0);
|
||||
|
||||
$result = $this->breadcrumbManager->build($route_match);
|
||||
$this->assertEquals($breadcrumb, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multiple breadcrumb builder with different priority.
|
||||
*/
|
||||
public function testBuildWithMultipleApplyingBuilders() {
|
||||
$builder1 = $this->getMock('Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface');
|
||||
$builder1->expects($this->never())
|
||||
->method('applies');
|
||||
$builder1->expects($this->never())
|
||||
->method('build');
|
||||
|
||||
$builder2 = $this->getMock('Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface');
|
||||
$breadcrumb2 = array('<a href="/example2">Test2</a>');
|
||||
$builder2->expects($this->once())
|
||||
->method('applies')
|
||||
->will($this->returnValue(TRUE));
|
||||
$builder2->expects($this->once())
|
||||
->method('build')
|
||||
->will($this->returnValue($breadcrumb2));
|
||||
|
||||
$route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
|
||||
|
||||
$this->moduleHandler->expects($this->once())
|
||||
->method('alter')
|
||||
->with('system_breadcrumb', $breadcrumb2, $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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multiple breadcrumb builders of which one returns NULL.
|
||||
*/
|
||||
public function testBuildWithOneNotApplyingBuilders() {
|
||||
$builder1 = $this->getMock('Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface');
|
||||
$builder1->expects($this->once())
|
||||
->method('applies')
|
||||
->will($this->returnValue(FALSE));
|
||||
$builder1->expects($this->never())
|
||||
->method('build');
|
||||
|
||||
$builder2 = $this->getMock('Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface');
|
||||
$breadcrumb2 = array('<a href="/example2">Test2</a>');
|
||||
$builder2->expects($this->once())
|
||||
->method('applies')
|
||||
->will($this->returnValue(TRUE));
|
||||
$builder2->expects($this->once())
|
||||
->method('build')
|
||||
->will($this->returnValue($breadcrumb2));
|
||||
|
||||
$route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
|
||||
|
||||
$this->moduleHandler->expects($this->once())
|
||||
->method('alter')
|
||||
->with('system_breadcrumb', $breadcrumb2, $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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a breadcrumb builder with a bad return value.
|
||||
*
|
||||
* @expectedException \UnexpectedValueException
|
||||
*/
|
||||
public function testBuildWithInvalidBreadcrumbResult() {
|
||||
$builder = $this->getMock('Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface');
|
||||
$builder->expects($this->once())
|
||||
->method('applies')
|
||||
->will($this->returnValue(TRUE));
|
||||
$builder->expects($this->once())
|
||||
->method('build')
|
||||
->will($this->returnValue('invalid_result'));
|
||||
|
||||
$this->breadcrumbManager->addBuilder($builder, 0);
|
||||
$this->breadcrumbManager->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,305 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Cache\BackendChainImplementationUnitTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Cache;
|
||||
|
||||
use Drupal\Core\Cache\BackendChain;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\MemoryBackend;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Unit test of backend chain implementation specifics.
|
||||
*
|
||||
* @group Cache
|
||||
*/
|
||||
class BackendChainImplementationUnitTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Chain that will be heavily tested.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\BackendChain
|
||||
*/
|
||||
protected $chain;
|
||||
|
||||
/**
|
||||
* First backend in the chain.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface
|
||||
*/
|
||||
protected $firstBackend;
|
||||
|
||||
/**
|
||||
* Second backend in the chain.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface
|
||||
*/
|
||||
protected $secondBackend;
|
||||
|
||||
/**
|
||||
* Third backend in the chain.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface
|
||||
*/
|
||||
protected $thirdBackend;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Set up three memory backends to be used in the chain.
|
||||
$this->firstBackend = new MemoryBackend('foo');
|
||||
$this->secondBackend = new MemoryBackend('bar');
|
||||
$this->thirdBackend = new MemoryBackend('baz');
|
||||
|
||||
// Set an initial fixed dataset for all testing. The next three data
|
||||
// collections will test two edge cases (last backend has the data, and
|
||||
// first backend has the data) and will test a normal use case (middle
|
||||
// backend has the data). We should have a complete unit test with those.
|
||||
// Note that in all cases, when the same key is set on more than one
|
||||
// backend, the values are voluntarily different, this ensures in which
|
||||
// backend we actually fetched the key when doing get calls.
|
||||
|
||||
// Set a key present on all backends (for delete).
|
||||
$this->firstBackend->set('t123', 1231);
|
||||
$this->secondBackend->set('t123', 1232);
|
||||
$this->thirdBackend->set('t123', 1233);
|
||||
|
||||
// Set a key present on the second and the third (for get), those two will
|
||||
// be different, this will ensure from where we get the key.
|
||||
$this->secondBackend->set('t23', 232);
|
||||
$this->thirdBackend->set('t23', 233);
|
||||
|
||||
// Set a key on only the third, we will ensure propagation using this one.
|
||||
$this->thirdBackend->set('t3', 33);
|
||||
|
||||
// Create the chain.
|
||||
$this->chain = new BackendChain('foobarbaz');
|
||||
$this->chain
|
||||
->appendBackend($this->firstBackend)
|
||||
->appendBackend($this->secondBackend)
|
||||
->appendBackend($this->thirdBackend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the get feature.
|
||||
*/
|
||||
public function testGet() {
|
||||
$cached = $this->chain->get('t123');
|
||||
$this->assertNotSame(FALSE, $cached, 'Got key that is on all backends');
|
||||
$this->assertSame(1231, $cached->data, 'Got the key from the backend 1');
|
||||
|
||||
$cached = $this->chain->get('t23');
|
||||
$this->assertNotSame(FALSE, $cached, 'Got key that is on backends 2 and 3');
|
||||
$this->assertSame(232, $cached->data, 'Got the key from the backend 2');
|
||||
|
||||
$cached = $this->chain->get('t3');
|
||||
$this->assertNotSame(FALSE, $cached, 'Got key that is on the backend 3');
|
||||
$this->assertSame(33, $cached->data, 'Got the key from the backend 3');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the get multiple feature.
|
||||
*/
|
||||
public function testGetMultiple() {
|
||||
$cids = array('t123', 't23', 't3', 't4');
|
||||
|
||||
$ret = $this->chain->getMultiple($cids);
|
||||
$this->assertSame($ret['t123']->data, 1231, 'Got key 123 and value is from the first backend');
|
||||
$this->assertSame($ret['t23']->data, 232, 'Got key 23 and value is from the second backend');
|
||||
$this->assertSame($ret['t3']->data, 33, 'Got key 3 and value is from the third backend');
|
||||
$this->assertFalse(array_key_exists('t4', $ret), "Didn't get the nonexistent key");
|
||||
|
||||
$this->assertFalse(in_array('t123', $cids), "Existing key 123 has been removed from &\$cids");
|
||||
$this->assertFalse(in_array('t23', $cids), "Existing key 23 has been removed from &\$cids");
|
||||
$this->assertFalse(in_array('t3', $cids), "Existing key 3 has been removed from &\$cids");
|
||||
$this->assertTrue(in_array('t4', $cids), "Non existing key 4 is still in &\$cids");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that set will propagate.
|
||||
*/
|
||||
public function testSet() {
|
||||
$this->chain->set('test', 123);
|
||||
|
||||
$cached = $this->firstBackend->get('test');
|
||||
$this->assertNotSame(FALSE, $cached, 'Test key is in the first backend');
|
||||
$this->assertSame(123, $cached->data, 'Test key has the right value');
|
||||
|
||||
$cached = $this->secondBackend->get('test');
|
||||
$this->assertNotSame(FALSE, $cached, 'Test key is in the second backend');
|
||||
$this->assertSame(123, $cached->data, 'Test key has the right value');
|
||||
|
||||
$cached = $this->thirdBackend->get('test');
|
||||
$this->assertNotSame(FALSE, $cached, 'Test key is in the third backend');
|
||||
$this->assertSame(123, $cached->data, 'Test key has the right value');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that delete will propagate.
|
||||
*/
|
||||
public function testDelete() {
|
||||
$this->chain->set('test', 5);
|
||||
|
||||
$cached = $this->firstBackend->get('test');
|
||||
$this->assertNotSame(FALSE, $cached, 'Test key has been added to the first backend');
|
||||
$cached = $this->secondBackend->get('test');
|
||||
$this->assertNotSame(FALSE, $cached, 'Test key has been added to the first backend');
|
||||
$cached = $this->thirdBackend->get('test');
|
||||
$this->assertNotSame(FALSE, $cached, 'Test key has been added to the first backend');
|
||||
|
||||
$this->chain->delete('test');
|
||||
|
||||
$cached = $this->firstBackend->get('test');
|
||||
$this->assertSame(FALSE, $cached, 'Test key is removed from the first backend');
|
||||
$cached = $this->secondBackend->get('test');
|
||||
$this->assertSame(FALSE, $cached, 'Test key is removed from the second backend');
|
||||
$cached = $this->thirdBackend->get('test');
|
||||
$this->assertSame(FALSE, $cached, 'Test key is removed from the third backend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure get values propagation to previous backends.
|
||||
*/
|
||||
public function testGetHasPropagated() {
|
||||
$this->chain->get('t23');
|
||||
$cached = $this->firstBackend->get('t23');
|
||||
$this->assertNotSame(FALSE, $cached, 'Test 2 has been propagated to the first backend');
|
||||
|
||||
$this->chain->get('t3');
|
||||
$cached = $this->firstBackend->get('t3');
|
||||
$this->assertNotSame(FALSE, $cached, 'Test 3 has been propagated to the first backend');
|
||||
$cached = $this->secondBackend->get('t3');
|
||||
$this->assertNotSame(FALSE, $cached, 'Test 3 has been propagated to the second backend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure get multiple values propagation to previous backends.
|
||||
*/
|
||||
public function testGetMultipleHasPropagated() {
|
||||
$cids = array('t3', 't23');
|
||||
$this->chain->getMultiple($cids);
|
||||
|
||||
$cached = $this->firstBackend->get('t3');
|
||||
$this->assertNotSame(FALSE, $cached, 'Test 3 has been propagated to the first backend');
|
||||
$this->assertSame(33, $cached->data, 'And value has been kept');
|
||||
$cached = $this->secondBackend->get('t3');
|
||||
$this->assertNotSame(FALSE, $cached, 'Test 3 has been propagated to the second backend');
|
||||
$this->assertSame(33, $cached->data, 'And value has been kept');
|
||||
|
||||
$cached = $this->firstBackend->get('t23');
|
||||
$this->assertNotSame(FALSE, $cached, 'Test 2 has been propagated to the first backend');
|
||||
$this->assertSame(232, $cached->data, 'And value has been kept');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the delete all operation is propagated to all backends in the chain.
|
||||
*/
|
||||
public function testDeleteAllPropagation() {
|
||||
// Set both expiring and permanent keys.
|
||||
$this->chain->set('test1', 1, Cache::PERMANENT);
|
||||
$this->chain->set('test2', 3, time() + 1000);
|
||||
$this->chain->deleteAll();
|
||||
|
||||
$this->assertFalse($this->firstBackend->get('test1'), 'First key has been deleted in first backend.');
|
||||
$this->assertFalse($this->firstBackend->get('test2'), 'Second key has been deleted in first backend.');
|
||||
$this->assertFalse($this->secondBackend->get('test1'), 'First key has been deleted in second backend.');
|
||||
$this->assertFalse($this->secondBackend->get('test2'), 'Second key has been deleted in second backend.');
|
||||
$this->assertFalse($this->thirdBackend->get('test1'), 'First key has been deleted in third backend.');
|
||||
$this->assertFalse($this->thirdBackend->get('test2'), 'Second key has been deleted in third backend.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the delete tags operation is propagated to all backends
|
||||
* in the chain.
|
||||
*/
|
||||
public function testDeleteTagsPropagation() {
|
||||
// Create two cache entries with the same tag and tag value.
|
||||
$this->chain->set('test_cid_clear1', 'foo', Cache::PERMANENT, array('test_tag:2'));
|
||||
$this->chain->set('test_cid_clear2', 'foo', Cache::PERMANENT, array('test_tag:2'));
|
||||
$this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
|
||||
&& $this->firstBackend->get('test_cid_clear2')
|
||||
&& $this->secondBackend->get('test_cid_clear1')
|
||||
&& $this->secondBackend->get('test_cid_clear2')
|
||||
&& $this->thirdBackend->get('test_cid_clear1')
|
||||
&& $this->thirdBackend->get('test_cid_clear2'),
|
||||
'Two cache items were created in all backends.');
|
||||
|
||||
// Invalidate test_tag of value 1. This should invalidate both entries.
|
||||
$this->chain->invalidateTags(array('test_tag:2'));
|
||||
$this->assertSame(FALSE, $this->firstBackend->get('test_cid_clear1')
|
||||
&& $this->firstBackend->get('test_cid_clear2')
|
||||
&& $this->secondBackend->get('test_cid_clear1')
|
||||
&& $this->secondBackend->get('test_cid_clear2')
|
||||
&& $this->thirdBackend->get('test_cid_clear1')
|
||||
&& $this->thirdBackend->get('test_cid_clear2'),
|
||||
'Two caches removed from all backends after clearing a cache tag.');
|
||||
|
||||
// Create two cache entries with the same tag and an array tag value.
|
||||
$this->chain->set('test_cid_clear1', 'foo', Cache::PERMANENT, array('test_tag:1'));
|
||||
$this->chain->set('test_cid_clear2', 'foo', Cache::PERMANENT, array('test_tag:1'));
|
||||
$this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
|
||||
&& $this->firstBackend->get('test_cid_clear2')
|
||||
&& $this->secondBackend->get('test_cid_clear1')
|
||||
&& $this->secondBackend->get('test_cid_clear2')
|
||||
&& $this->thirdBackend->get('test_cid_clear1')
|
||||
&& $this->thirdBackend->get('test_cid_clear2'),
|
||||
'Two cache items were created in all backends.');
|
||||
|
||||
// Invalidate test_tag of value 1. This should invalidate both entries.
|
||||
$this->chain->invalidateTags(array('test_tag:1'));
|
||||
$this->assertSame(FALSE, $this->firstBackend->get('test_cid_clear1')
|
||||
&& $this->firstBackend->get('test_cid_clear2')
|
||||
&& $this->secondBackend->get('test_cid_clear1')
|
||||
&& $this->secondBackend->get('test_cid_clear2')
|
||||
&& $this->thirdBackend->get('test_cid_clear1')
|
||||
&& $this->thirdBackend->get('test_cid_clear2'),
|
||||
'Two caches removed from all backends after clearing a cache tag.');
|
||||
|
||||
// Create three cache entries with a mix of tags and tag values.
|
||||
$this->chain->set('test_cid_clear1', 'foo', Cache::PERMANENT, array('test_tag:1'));
|
||||
$this->chain->set('test_cid_clear2', 'foo', Cache::PERMANENT, array('test_tag:2'));
|
||||
$this->chain->set('test_cid_clear3', 'foo', Cache::PERMANENT, array('test_tag_foo:3'));
|
||||
$this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
|
||||
&& $this->firstBackend->get('test_cid_clear2')
|
||||
&& $this->firstBackend->get('test_cid_clear3')
|
||||
&& $this->secondBackend->get('test_cid_clear1')
|
||||
&& $this->secondBackend->get('test_cid_clear2')
|
||||
&& $this->secondBackend->get('test_cid_clear3')
|
||||
&& $this->thirdBackend->get('test_cid_clear1')
|
||||
&& $this->thirdBackend->get('test_cid_clear2')
|
||||
&& $this->thirdBackend->get('test_cid_clear3'),
|
||||
'Three cached items were created in all backends.');
|
||||
|
||||
$this->chain->invalidateTags(array('test_tag_foo:3'));
|
||||
$this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
|
||||
&& $this->firstBackend->get('test_cid_clear2')
|
||||
&& $this->secondBackend->get('test_cid_clear1')
|
||||
&& $this->secondBackend->get('test_cid_clear2')
|
||||
&& $this->thirdBackend->get('test_cid_clear1')
|
||||
&& $this->thirdBackend->get('test_cid_clear2'),
|
||||
'Cached items not matching the tag were not cleared from any of the backends.');
|
||||
|
||||
$this->assertSame(FALSE, $this->firstBackend->get('test_cid_clear3')
|
||||
&& $this->secondBackend->get('test_cid_clear3')
|
||||
&& $this->thirdBackend->get('test_cid_clear3'),
|
||||
'Cached item matching the tag was removed from all backends.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that removing bin propagates to all backends.
|
||||
*/
|
||||
public function testRemoveBin() {
|
||||
$chain = new BackendChain('foo');
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
$backend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
|
||||
$backend->expects($this->once())->method('removeBin');
|
||||
$chain->appendBackend($backend);
|
||||
}
|
||||
|
||||
$chain->removeBin();
|
||||
}
|
||||
}
|
72
core/tests/Drupal/Tests/Core/Cache/CacheCollectorHelper.php
Normal file
72
core/tests/Drupal/Tests/Core/Cache/CacheCollectorHelper.php
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Cache\CacheCollectorHelper.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Cache;
|
||||
|
||||
use Drupal\Core\Cache\CacheCollector;
|
||||
|
||||
/**
|
||||
* Helper class to test the cache collector.
|
||||
*/
|
||||
class CacheCollectorHelper extends CacheCollector {
|
||||
|
||||
/**
|
||||
* Contains data to return on a cache miss.
|
||||
* @var array
|
||||
*/
|
||||
protected $cacheMissData = array();
|
||||
|
||||
/**
|
||||
* Number of calls to \Drupal\Core\Cache\CacheCollector::resolveCacheMiss().
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $cacheMisses = 0;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set($key, $value) {
|
||||
parent::set($key, $value);
|
||||
$this->persist($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolveCacheMiss($key) {
|
||||
$this->cacheMisses++;
|
||||
if (isset($this->cacheMissData[$key])) {
|
||||
$this->storage[$key] = $this->cacheMissData[$key];
|
||||
$this->persist($key);
|
||||
return $this->cacheMissData[$key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets data to return from a cache miss resolve.
|
||||
*
|
||||
* @param string $key
|
||||
* The key being looked for.
|
||||
* @param mixed $value
|
||||
* The value to return.
|
||||
*/
|
||||
public function setCacheMissData($key, $value) {
|
||||
$this->cacheMissData[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of cache misses.
|
||||
*
|
||||
* @return int
|
||||
* Number of calls to the resolve cache miss method.
|
||||
*/
|
||||
public function getCacheMisses() {
|
||||
return $this->cacheMisses;
|
||||
}
|
||||
|
||||
}
|
422
core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php
Normal file
422
core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php
Normal file
|
@ -0,0 +1,422 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Cache\CacheCollectorTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Cache;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Cache\CacheCollector
|
||||
* @group Cache
|
||||
*/
|
||||
class CacheCollectorTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The cache backend that should be used.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $cacheBackend;
|
||||
|
||||
/**
|
||||
* The cache tags invalidator.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $cacheTagsInvalidator;
|
||||
|
||||
/**
|
||||
* The lock backend that should be used.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $lock;
|
||||
|
||||
/**
|
||||
* The cache id used for the test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $cid;
|
||||
|
||||
/**
|
||||
* Cache collector implementation to test.
|
||||
*
|
||||
* @var \Drupal\Tests\Core\Cache\CacheCollectorHelper
|
||||
*/
|
||||
protected $collector;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
|
||||
$this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
|
||||
$this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface');
|
||||
$this->cid = $this->randomMachineName();
|
||||
$this->collector = new CacheCollectorHelper($this->cid, $this->cacheBackend, $this->lock);
|
||||
|
||||
$this->getContainerWithCacheTagsInvalidator($this->cacheTagsInvalidator);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the resolve cache miss function.
|
||||
*/
|
||||
public function testResolveCacheMiss() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
$this->collector->setCacheMissData($key, $value);
|
||||
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests setting and getting values when the cache is empty.
|
||||
*/
|
||||
public function testSetAndGet() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
|
||||
$this->assertNull($this->collector->get($key));
|
||||
|
||||
$this->collector->set($key, $value);
|
||||
$this->assertTrue($this->collector->has($key));
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes sure that NULL is a valid value and is collected.
|
||||
*/
|
||||
public function testSetAndGetNull() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = NULL;
|
||||
|
||||
$this->cacheBackend->expects($this->once())
|
||||
->method('invalidate')
|
||||
->with($this->cid);
|
||||
$this->collector->set($key, $value);
|
||||
$this->assertTrue($this->collector->has($key));
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
|
||||
// Ensure that getting a value that isn't set does not mark it as
|
||||
// existent.
|
||||
$non_existing_key = $this->randomMachineName(7);
|
||||
$this->collector->get($non_existing_key);
|
||||
$this->assertFalse($this->collector->has($non_existing_key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests returning value from the collected cache.
|
||||
*/
|
||||
public function testGetFromCache() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
|
||||
$cache = (object) array(
|
||||
'data' => array($key => $value),
|
||||
'created' => (int) $_SERVER['REQUEST_TIME'],
|
||||
);
|
||||
$this->cacheBackend->expects($this->once())
|
||||
->method('get')
|
||||
->with($this->cid)
|
||||
->will($this->returnValue($cache));
|
||||
$this->assertTrue($this->collector->has($key));
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
$this->assertEquals(0, $this->collector->getCacheMisses());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests setting and deleting values.
|
||||
*/
|
||||
public function testDelete() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
|
||||
$this->assertNull($this->collector->get($key));
|
||||
|
||||
$this->collector->set($key, $value);
|
||||
$this->assertTrue($this->collector->has($key));
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
|
||||
$this->cacheBackend->expects($this->once())
|
||||
->method('invalidate')
|
||||
->with($this->cid);
|
||||
$this->collector->delete($key);
|
||||
$this->assertFalse($this->collector->has($key));
|
||||
$this->assertEquals(NULL, $this->collector->get($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests updating the cache when no changes were made.
|
||||
*/
|
||||
public function testUpdateCacheNoChanges() {
|
||||
$this->lock->expects($this->never())
|
||||
->method('acquire');
|
||||
$this->cacheBackend->expects($this->never())
|
||||
->method('set');
|
||||
|
||||
// Destruct the object to trigger the update data process.
|
||||
$this->collector->destruct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests updating the cache after a set.
|
||||
*/
|
||||
public function testUpdateCache() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
|
||||
$this->collector->setCacheMissData($key, $value);
|
||||
$this->collector->get($key);
|
||||
|
||||
// Set up mock objects for the expected calls, first a lock acquire, then
|
||||
// cache get to look for conflicting cache entries, then a cache set and
|
||||
// finally the lock is released again.
|
||||
$this->lock->expects($this->once())
|
||||
->method('acquire')
|
||||
->with($this->cid . ':Drupal\Core\Cache\CacheCollector')
|
||||
->will($this->returnValue(TRUE));
|
||||
$this->cacheBackend->expects($this->once())
|
||||
->method('get')
|
||||
->with($this->cid, FALSE);
|
||||
$this->cacheBackend->expects($this->once())
|
||||
->method('set')
|
||||
->with($this->cid, array($key => $value), Cache::PERMANENT, array());
|
||||
$this->lock->expects($this->once())
|
||||
->method('release')
|
||||
->with($this->cid . ':Drupal\Core\Cache\CacheCollector');
|
||||
|
||||
// Destruct the object to trigger the update data process.
|
||||
$this->collector->destruct();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests updating the cache when the lock acquire fails.
|
||||
*/
|
||||
public function testUpdateCacheLockFail() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
|
||||
$this->collector->setCacheMissData($key, $value);
|
||||
$this->collector->get($key);
|
||||
|
||||
// The lock acquire returns false, so the method should abort.
|
||||
$this->lock->expects($this->once())
|
||||
->method('acquire')
|
||||
->with($this->cid . ':Drupal\Core\Cache\CacheCollector')
|
||||
->will($this->returnValue(FALSE));
|
||||
$this->cacheBackend->expects($this->never())
|
||||
->method('set');
|
||||
|
||||
// Destruct the object to trigger the update data process.
|
||||
$this->collector->destruct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests updating the cache when there is a conflict after cache invalidation.
|
||||
*/
|
||||
public function testUpdateCacheInvalidatedConflict() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
|
||||
$cache = (object) array(
|
||||
'data' => array($key => $value),
|
||||
'created' => (int) $_SERVER['REQUEST_TIME'],
|
||||
);
|
||||
$this->cacheBackend->expects($this->at(0))
|
||||
->method('get')
|
||||
->with($this->cid)
|
||||
->will($this->returnValue($cache));
|
||||
|
||||
$this->cacheBackend->expects($this->at(1))
|
||||
->method('invalidate')
|
||||
->with($this->cid);
|
||||
$this->collector->set($key, 'new value');
|
||||
|
||||
// Set up mock objects for the expected calls, first a lock acquire, then
|
||||
// cache get to look for conflicting cache entries, which does find
|
||||
// and then it deletes the cache and aborts.
|
||||
$this->lock->expects($this->once())
|
||||
->method('acquire')
|
||||
->with($this->cid . ':Drupal\Core\Cache\CacheCollector')
|
||||
->will($this->returnValue(TRUE));
|
||||
$cache = (object) array(
|
||||
'data' => array($key => $value),
|
||||
'created' => (int) $_SERVER['REQUEST_TIME'] + 1,
|
||||
);
|
||||
$this->cacheBackend->expects($this->at(0))
|
||||
->method('get')
|
||||
->with($this->cid)
|
||||
->will($this->returnValue($cache));
|
||||
$this->cacheBackend->expects($this->once())
|
||||
->method('delete')
|
||||
->with($this->cid);
|
||||
$this->lock->expects($this->once())
|
||||
->method('release')
|
||||
->with($this->cid . ':Drupal\Core\Cache\CacheCollector');
|
||||
|
||||
// Destruct the object to trigger the update data process.
|
||||
$this->collector->destruct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests updating the cache when a different request
|
||||
*/
|
||||
public function testUpdateCacheMerge() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
|
||||
$this->collector->setCacheMissData($key, $value);
|
||||
$this->collector->get($key);
|
||||
|
||||
// Set up mock objects for the expected calls, first a lock acquire, then
|
||||
// cache get to look for existing cache entries, which does find
|
||||
// and then it merges them.
|
||||
$this->lock->expects($this->once())
|
||||
->method('acquire')
|
||||
->with($this->cid . ':Drupal\Core\Cache\CacheCollector')
|
||||
->will($this->returnValue(TRUE));
|
||||
$cache = (object) array(
|
||||
'data' => array('other key' => 'other value'),
|
||||
'created' => (int) $_SERVER['REQUEST_TIME'] + 1,
|
||||
);
|
||||
$this->cacheBackend->expects($this->at(0))
|
||||
->method('get')
|
||||
->with($this->cid)
|
||||
->will($this->returnValue($cache));
|
||||
$this->cacheBackend->expects($this->once())
|
||||
->method('set')
|
||||
->with($this->cid, array('other key' => 'other value', $key => $value), Cache::PERMANENT, array());
|
||||
$this->lock->expects($this->once())
|
||||
->method('release')
|
||||
->with($this->cid . ':Drupal\Core\Cache\CacheCollector');
|
||||
|
||||
// Destruct the object to trigger the update data process.
|
||||
$this->collector->destruct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests updating the cache after a delete.
|
||||
*/
|
||||
public function testUpdateCacheDelete() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
|
||||
$cache = (object) array(
|
||||
'data' => array($key => $value),
|
||||
'created' => (int) $_SERVER['REQUEST_TIME'],
|
||||
);
|
||||
$this->cacheBackend->expects($this->at(0))
|
||||
->method('get')
|
||||
->with($this->cid)
|
||||
->will($this->returnValue($cache));
|
||||
|
||||
$this->collector->delete($key);
|
||||
|
||||
// Set up mock objects for the expected calls, first a lock acquire, then
|
||||
// cache get to look for conflicting cache entries, then a cache set and
|
||||
// finally the lock is released again.
|
||||
$this->lock->expects($this->once())
|
||||
->method('acquire')
|
||||
->with($this->cid . ':Drupal\Core\Cache\CacheCollector')
|
||||
->will($this->returnValue(TRUE));
|
||||
// The second argument is set to TRUE because we triggered a cache
|
||||
// invalidation.
|
||||
$this->cacheBackend->expects($this->at(0))
|
||||
->method('get')
|
||||
->with($this->cid, TRUE);
|
||||
$this->cacheBackend->expects($this->once())
|
||||
->method('set')
|
||||
->with($this->cid, array(), Cache::PERMANENT, array());
|
||||
$this->lock->expects($this->once())
|
||||
->method('release')
|
||||
->with($this->cid . ':Drupal\Core\Cache\CacheCollector');
|
||||
|
||||
// Destruct the object to trigger the update data process.
|
||||
$this->collector->destruct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a reset of the cache collector.
|
||||
*/
|
||||
public function testUpdateCacheReset() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
|
||||
// Set the data and request it.
|
||||
$this->collector->setCacheMissData($key, $value);
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
|
||||
// Should have been added to the storage and only be requested once.
|
||||
$this->assertEquals(1, $this->collector->getCacheMisses());
|
||||
|
||||
// Reset the collected cache, should call it again.
|
||||
$this->collector->reset();
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
$this->assertEquals(2, $this->collector->getCacheMisses());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a clear of the cache collector.
|
||||
*/
|
||||
public function testUpdateCacheClear() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
|
||||
// Set the data and request it.
|
||||
$this->collector->setCacheMissData($key, $value);
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
|
||||
// Should have been added to the storage and only be requested once.
|
||||
$this->assertEquals(1, $this->collector->getCacheMisses());
|
||||
|
||||
// Clear the collected cache, should call it again.
|
||||
$this->cacheBackend->expects($this->once())
|
||||
->method('delete')
|
||||
->with($this->cid);
|
||||
$this->cacheTagsInvalidator->expects($this->never())
|
||||
->method('invalidateTags');
|
||||
$this->collector->clear();
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
$this->assertEquals(2, $this->collector->getCacheMisses());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a clear of the cache collector using tags.
|
||||
*/
|
||||
public function testUpdateCacheClearTags() {
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
$tags = array($this->randomMachineName());
|
||||
$this->collector = new CacheCollectorHelper($this->cid, $this->cacheBackend, $this->lock, $tags);
|
||||
|
||||
// Set the data and request it.
|
||||
$this->collector->setCacheMissData($key, $value);
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
|
||||
// Should have been added to the storage and only be requested once.
|
||||
$this->assertEquals(1, $this->collector->getCacheMisses());
|
||||
|
||||
// Clear the collected cache using the tags, should call it again.
|
||||
$this->cacheBackend->expects($this->never())
|
||||
->method('delete');
|
||||
$this->cacheTagsInvalidator->expects($this->once())
|
||||
->method('invalidateTags')
|
||||
->with($tags);
|
||||
$this->collector->clear();
|
||||
$this->assertEquals($value, $this->collector->get($key));
|
||||
$this->assertEquals(2, $this->collector->getCacheMisses());
|
||||
}
|
||||
|
||||
}
|
109
core/tests/Drupal/Tests/Core/Cache/CacheFactoryTest.php
Normal file
109
core/tests/Drupal/Tests/Core/Cache/CacheFactoryTest.php
Normal file
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Cache\CacheFactoryTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Cache;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\Cache\CacheFactory;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Cache\CacheFactory
|
||||
* @group Cache
|
||||
*/
|
||||
class CacheFactoryTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Test that the cache factory falls back to the built-in default service.
|
||||
*
|
||||
* @covers ::__construct
|
||||
* @covers ::get
|
||||
*/
|
||||
public function testCacheFactoryWithDefaultSettings() {
|
||||
$settings = new Settings(array());
|
||||
$cache_factory = new CacheFactory($settings);
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$cache_factory->setContainer($container);
|
||||
|
||||
$builtin_default_backend_factory = $this->getMock('\Drupal\Core\Cache\CacheFactoryInterface');
|
||||
$container->set('cache.backend.database', $builtin_default_backend_factory);
|
||||
|
||||
$render_bin = $this->getMock('\Drupal\Core\Cache\CacheBackendInterface');
|
||||
$builtin_default_backend_factory->expects($this->once())
|
||||
->method('get')
|
||||
->with('render')
|
||||
->will($this->returnValue($render_bin));
|
||||
|
||||
$actual_bin = $cache_factory->get('render');
|
||||
$this->assertSame($render_bin, $actual_bin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the cache factory falls back to customized default service.
|
||||
*
|
||||
* @covers ::__construct
|
||||
* @covers ::get
|
||||
*/
|
||||
public function testCacheFactoryWithCustomizedDefaultBackend() {
|
||||
$settings = new Settings(array(
|
||||
'cache' => array(
|
||||
'default' => 'cache.backend.custom',
|
||||
),
|
||||
));
|
||||
$cache_factory = new CacheFactory($settings);
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$cache_factory->setContainer($container);
|
||||
|
||||
$custom_default_backend_factory = $this->getMock('\Drupal\Core\Cache\CacheFactoryInterface');
|
||||
$container->set('cache.backend.custom', $custom_default_backend_factory);
|
||||
|
||||
$render_bin = $this->getMock('\Drupal\Core\Cache\CacheBackendInterface');
|
||||
$custom_default_backend_factory->expects($this->once())
|
||||
->method('get')
|
||||
->with('render')
|
||||
->will($this->returnValue($render_bin));
|
||||
|
||||
$actual_bin = $cache_factory->get('render');
|
||||
$this->assertSame($render_bin, $actual_bin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the cache factory picks the correct per-bin service.
|
||||
*
|
||||
* @covers ::__construct
|
||||
* @covers ::get
|
||||
*/
|
||||
public function testCacheFactoryWithSpecifiedPerBinBackend() {
|
||||
$settings = new Settings(array(
|
||||
'cache' => array(
|
||||
'bins' => array(
|
||||
'render' => 'cache.backend.custom',
|
||||
),
|
||||
),
|
||||
));
|
||||
$cache_factory = new CacheFactory($settings);
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$cache_factory->setContainer($container);
|
||||
|
||||
$custom_render_backend_factory = $this->getMock('\Drupal\Core\Cache\CacheFactoryInterface');
|
||||
$container->set('cache.backend.custom', $custom_render_backend_factory);
|
||||
|
||||
$render_bin = $this->getMock('\Drupal\Core\Cache\CacheBackendInterface');
|
||||
$custom_render_backend_factory->expects($this->once())
|
||||
->method('get')
|
||||
->with('render')
|
||||
->will($this->returnValue($render_bin));
|
||||
|
||||
$actual_bin = $cache_factory->get('render');
|
||||
$this->assertSame($render_bin, $actual_bin);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Cache\CacheTagsInvalidatorTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Cache;
|
||||
|
||||
use Drupal\Core\Cache\CacheTagsInvalidator;
|
||||
use Drupal\Core\DependencyInjection\Container;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Cache\CacheTagsInvalidator
|
||||
* @group Cache
|
||||
*/
|
||||
class CacheTagsInvalidatorTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @covers ::invalidateTags
|
||||
*
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage Cache tags must be strings, array given.
|
||||
*/
|
||||
public function testInvalidateTagsWithInvalidTags() {
|
||||
$cache_tags_invalidator = new CacheTagsInvalidator();
|
||||
$cache_tags_invalidator->invalidateTags(['node' => [2, 3, 5, 8, 13]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::invalidateTags
|
||||
* @covers ::addInvalidator
|
||||
*/
|
||||
public function testInvalidateTags() {
|
||||
$cache_tags_invalidator = new CacheTagsInvalidator();
|
||||
|
||||
// This does not actually implement,
|
||||
// \Drupal\Cache\Cache\CacheBackendInterface but we can not mock from two
|
||||
// interfaces, we would need a test class for that.
|
||||
$invalidator_cache_bin = $this->getMock('\Drupal\Core\Cache\CacheTagsInvalidator');
|
||||
$invalidator_cache_bin->expects($this->once())
|
||||
->method('invalidateTags')
|
||||
->with(array('node:1'));
|
||||
|
||||
// We do not have to define that invalidateTags() is never called as the
|
||||
// interface does not define that method, trying to call it would result in
|
||||
// a fatal error.
|
||||
$non_invalidator_cache_bin = $this->getMock('\Drupal\Core\Cache\CacheBackendInterface');
|
||||
|
||||
$container = new Container();
|
||||
$container->set('cache.invalidator_cache_bin', $invalidator_cache_bin);
|
||||
$container->set('cache.non_invalidator_cache_bin', $non_invalidator_cache_bin);
|
||||
$container->setParameter('cache_bins', array('cache.invalidator_cache_bin' => 'invalidator_cache_bin', 'cache.non_invalidator_cache_bin' => 'non_invalidator_cache_bin'));
|
||||
$cache_tags_invalidator->setContainer($container);
|
||||
|
||||
$invalidator = $this->getMock('\Drupal\Core\Cache\CacheTagsInvalidator');
|
||||
$invalidator->expects($this->once())
|
||||
->method('invalidateTags')
|
||||
->with(array('node:1'));
|
||||
|
||||
$cache_tags_invalidator->addInvalidator($invalidator);
|
||||
|
||||
$cache_tags_invalidator->invalidateTags(array('node:1'));
|
||||
}
|
||||
|
||||
}
|
156
core/tests/Drupal/Tests/Core/Cache/CacheTest.php
Normal file
156
core/tests/Drupal/Tests/Core/Cache/CacheTest.php
Normal file
|
@ -0,0 +1,156 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Cache\CacheTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Cache;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Cache\Cache
|
||||
* @group Cache
|
||||
*/
|
||||
class CacheTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Provides a list of cache tags arrays.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function validateTagsProvider() {
|
||||
return [
|
||||
[[], FALSE],
|
||||
[['foo'], FALSE],
|
||||
[['foo', 'bar'], FALSE],
|
||||
[['foo', 'bar', 'llama:2001988', 'baz', 'llama:14031991'], FALSE],
|
||||
// Invalid.
|
||||
[[FALSE], 'Cache tags must be strings, boolean given.'],
|
||||
[[TRUE], 'Cache tags must be strings, boolean given.'],
|
||||
[['foo', FALSE], 'Cache tags must be strings, boolean given.'],
|
||||
[[NULL], 'Cache tags must be strings, NULL given.'],
|
||||
[['foo', NULL], 'Cache tags must be strings, NULL given.'],
|
||||
[[1337], 'Cache tags must be strings, integer given.'],
|
||||
[['foo', 1337], 'Cache tags must be strings, integer given.'],
|
||||
[[3.14], 'Cache tags must be strings, double given.'],
|
||||
[['foo', 3.14], 'Cache tags must be strings, double given.'],
|
||||
[[[]], 'Cache tags must be strings, array given.'],
|
||||
[['foo', []], 'Cache tags must be strings, array given.'],
|
||||
[['foo', ['bar']], 'Cache tags must be strings, array given.'],
|
||||
[[new \stdClass()], 'Cache tags must be strings, object given.'],
|
||||
[['foo', new \stdClass()], 'Cache tags must be strings, object given.'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::validateTags
|
||||
*
|
||||
* @dataProvider validateTagsProvider
|
||||
*/
|
||||
public function testValidateTags(array $tags, $expected_exception_message) {
|
||||
if ($expected_exception_message !== FALSE) {
|
||||
$this->setExpectedException('LogicException', $expected_exception_message);
|
||||
}
|
||||
// If it doesn't throw an exception, validateTags() returns NULL.
|
||||
$this->assertNull(Cache::validateTags($tags));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of pairs of cache tags arrays to be merged.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function mergeTagsProvider() {
|
||||
return [
|
||||
[[], [], []],
|
||||
[['bar'], ['foo'], ['bar', 'foo']],
|
||||
[['foo'], ['bar'], ['bar', 'foo']],
|
||||
[['foo'], ['bar', 'foo'], ['bar', 'foo']],
|
||||
[['foo'], ['foo', 'bar'], ['bar', 'foo']],
|
||||
[['bar', 'foo'], ['foo', 'bar'], ['bar', 'foo']],
|
||||
[['foo', 'bar'], ['foo', 'bar'], ['bar', 'foo']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::mergeTags
|
||||
*
|
||||
* @dataProvider mergeTagsProvider
|
||||
*/
|
||||
public function testMergeTags(array $a, array $b, array $expected) {
|
||||
$this->assertEquals($expected, Cache::mergeTags($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of pairs of cache tags arrays to be merged.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function mergeMaxAgesProvider() {
|
||||
return [
|
||||
[Cache::PERMANENT, Cache::PERMANENT, Cache::PERMANENT],
|
||||
[60, 60, 60],
|
||||
[0, 0, 0],
|
||||
|
||||
[60, 0, 0],
|
||||
[0, 60, 0],
|
||||
|
||||
[Cache::PERMANENT, 0, 0],
|
||||
[0, Cache::PERMANENT, 0],
|
||||
|
||||
[Cache::PERMANENT, 60, 60],
|
||||
[60, Cache::PERMANENT, 60],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @covers ::mergeMaxAges
|
||||
*
|
||||
* @dataProvider mergeMaxAgesProvider
|
||||
*/
|
||||
public function testMergeMaxAges($a, $b, $expected) {
|
||||
$this->assertSame($expected, Cache::mergeMaxAges($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of pairs of (prefix, suffixes) to build cache tags from.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function buildTagsProvider() {
|
||||
return [
|
||||
['node', [1], ['node:1']],
|
||||
['node', [1, 2, 3], ['node:1', 'node:2', 'node:3']],
|
||||
['node', [3, 2, 1], ['node:3', 'node:2', 'node:1']],
|
||||
['node', [NULL], ['node:']],
|
||||
['node', [TRUE, FALSE], ['node:1', 'node:']],
|
||||
['node', ['a', 'z', 'b'], ['node:a', 'node:z', 'node:b']],
|
||||
// No suffixes, no cache tags.
|
||||
['', [], []],
|
||||
['node', [], []],
|
||||
// Only suffix values matter, not keys: verify that expectation.
|
||||
['node', [5 => 145, 4545 => 3], ['node:145', 'node:3']],
|
||||
['node', [5 => TRUE], ['node:1']],
|
||||
['node', [5 => NULL], ['node:']],
|
||||
['node', ['a' => NULL], ['node:']],
|
||||
['node', ['a' => TRUE], ['node:1']],
|
||||
// Test the $glue parameter.
|
||||
['config:system.menu', ['menu_name'], ['config:system.menu.menu_name'], '.'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::buildTags
|
||||
*
|
||||
* @dataProvider buildTagsProvider
|
||||
*/
|
||||
public function testBuildTags($prefix, array $suffixes, array $expected, $glue = ':') {
|
||||
$this->assertEquals($expected, Cache::buildTags($prefix, $suffixes, $glue));
|
||||
}
|
||||
|
||||
}
|
187
core/tests/Drupal/Tests/Core/Cache/CacheableMetadataTest.php
Normal file
187
core/tests/Drupal/Tests/Core/Cache/CacheableMetadataTest.php
Normal file
|
@ -0,0 +1,187 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Cache\CacheableMetadataTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Cache;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Tests\Core\Render\TestCacheableDependency;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Cache\CacheableMetadata
|
||||
* @group Cache
|
||||
*/
|
||||
class CacheableMetadataTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @covers ::merge
|
||||
* @dataProvider providerTestMerge
|
||||
*
|
||||
* This only tests at a high level, because it reuses existing logic. Detailed
|
||||
* tests exist for the existing logic:
|
||||
*
|
||||
* @see \Drupal\Tests\Core\Cache\CacheTest::testMergeTags()
|
||||
* @see \Drupal\Tests\Core\Cache\CacheTest::testMergeMaxAges()
|
||||
* @see \Drupal\Tests\Core\Cache\CacheContextsTest
|
||||
*/
|
||||
public function testMerge(CacheableMetadata $a, CacheableMetadata $b, CacheableMetadata $expected) {
|
||||
$cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('cache_contexts_manager', $cache_contexts_manager);
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$this->assertEquals($expected, $a->merge($b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testMerge().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestMerge() {
|
||||
return [
|
||||
// All empty.
|
||||
[(new CacheableMetadata()), (new CacheableMetadata()), (new CacheableMetadata())],
|
||||
// Cache contexts.
|
||||
[(new CacheableMetadata())->setCacheContexts(['foo']), (new CacheableMetadata())->setCacheContexts(['bar']), (new CacheableMetadata())->setCacheContexts(['bar', 'foo'])],
|
||||
// Cache tags.
|
||||
[(new CacheableMetadata())->setCacheTags(['foo']), (new CacheableMetadata())->setCacheTags(['bar']), (new CacheableMetadata())->setCacheTags(['bar', 'foo'])],
|
||||
// Cache max-ages.
|
||||
[(new CacheableMetadata())->setCacheMaxAge(60), (new CacheableMetadata())->setCacheMaxAge(Cache::PERMANENT), (new CacheableMetadata())->setCacheMaxAge(60)],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* This delegates to Cache::mergeTags(), so just a basic test.
|
||||
*
|
||||
* @covers ::addCacheTags
|
||||
*/
|
||||
public function testAddCacheTags() {
|
||||
$metadata = new CacheableMetadata();
|
||||
$add_expected = [
|
||||
[ [], [] ],
|
||||
[ ['foo:bar'], ['foo:bar'] ],
|
||||
[ ['foo:baz'], ['foo:bar', 'foo:baz'] ],
|
||||
[ ['axx:first', 'foo:baz'], ['axx:first', 'foo:bar', 'foo:baz'] ],
|
||||
[ [], ['axx:first', 'foo:bar', 'foo:baz'] ],
|
||||
[ ['axx:first'], ['axx:first', 'foo:bar', 'foo:baz'] ],
|
||||
];
|
||||
|
||||
foreach ($add_expected as $data) {
|
||||
list($add, $expected) = $data;
|
||||
$metadata->addCacheTags($add);
|
||||
$this->assertEquals($expected, $metadata->getCacheTags());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test valid and invalid values as max age.
|
||||
*
|
||||
* @covers ::setCacheMaxAge
|
||||
* @dataProvider providerSetCacheMaxAge
|
||||
*/
|
||||
public function testSetCacheMaxAge($data, $expect_exception) {
|
||||
$metadata = new CacheableMetadata();
|
||||
if ($expect_exception) {
|
||||
$this->setExpectedException('\InvalidArgumentException');
|
||||
}
|
||||
$metadata->setCacheMaxAge($data);
|
||||
$this->assertEquals($data, $metadata->getCacheMaxAge());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testSetCacheMaxAge.
|
||||
*/
|
||||
public function providerSetCacheMaxAge() {
|
||||
return [
|
||||
[0 , FALSE],
|
||||
['http', TRUE],
|
||||
['0', TRUE],
|
||||
[new \stdClass(), TRUE],
|
||||
[300, FALSE],
|
||||
[[], TRUE],
|
||||
[8.0, TRUE]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::createFromRenderArray
|
||||
* @dataProvider providerTestCreateFromRenderArray
|
||||
*/
|
||||
public function testCreateFromRenderArray(array $render_array, CacheableMetadata $expected) {
|
||||
$this->assertEquals($expected, CacheableMetadata::createFromRenderArray($render_array));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for createFromRenderArray().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestCreateFromRenderArray() {
|
||||
$data = [];
|
||||
|
||||
$empty_metadata = new CacheableMetadata();
|
||||
$nonempty_metadata = new CacheableMetadata();
|
||||
$nonempty_metadata->setCacheContexts(['qux'])
|
||||
->setCacheTags(['foo:bar']);
|
||||
|
||||
$empty_render_array = [];
|
||||
$nonempty_render_array = [
|
||||
'#cache' => [
|
||||
'contexts' => ['qux'],
|
||||
'tags' => ['foo:bar'],
|
||||
'max-age' => Cache::PERMANENT,
|
||||
],
|
||||
];
|
||||
|
||||
$data[] = [$empty_render_array, $empty_metadata];
|
||||
$data[] = [$nonempty_render_array, $nonempty_metadata];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::createFromObject
|
||||
* @dataProvider providerTestCreateFromObject
|
||||
*/
|
||||
public function testCreateFromObject($object, CacheableMetadata $expected) {
|
||||
$this->assertEquals($expected, CacheableMetadata::createFromObject($object));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for createFromObject().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestCreateFromObject() {
|
||||
$data = [];
|
||||
|
||||
$empty_metadata = new CacheableMetadata();
|
||||
$nonempty_metadata = new CacheableMetadata();
|
||||
$nonempty_metadata->setCacheContexts(['qux'])
|
||||
->setCacheTags(['foo:bar'])
|
||||
->setCacheMaxAge(600);
|
||||
$uncacheable_metadata = new CacheableMetadata();
|
||||
$uncacheable_metadata->setCacheMaxAge(0);
|
||||
|
||||
$empty_cacheable_object = new TestCacheableDependency([], [], Cache::PERMANENT);
|
||||
$nonempty_cacheable_object = new TestCacheableDependency(['qux'], ['foo:bar'], 600);
|
||||
$uncacheable_object = new \stdClass();
|
||||
|
||||
$data[] = [$empty_cacheable_object, $empty_metadata];
|
||||
$data[] = [$nonempty_cacheable_object, $nonempty_metadata];
|
||||
$data[] = [$uncacheable_object, $uncacheable_metadata];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
116
core/tests/Drupal/Tests/Core/Cache/ChainedFastBackendTest.php
Normal file
116
core/tests/Drupal/Tests/Core/Cache/ChainedFastBackendTest.php
Normal file
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Cache\ChainedFastBackendTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Cache;
|
||||
|
||||
use Drupal\Core\Cache\ChainedFastBackend;
|
||||
use Drupal\Core\Cache\MemoryBackend;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Cache\ChainedFastBackend
|
||||
* @group Cache
|
||||
*/
|
||||
class ChainedFastBackendTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The consistent cache backend.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface
|
||||
*/
|
||||
protected $consistentCache;
|
||||
|
||||
/**
|
||||
* The fast cache backend.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface
|
||||
*/
|
||||
protected $fastCache;
|
||||
|
||||
/**
|
||||
* The cache bin.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $bin;
|
||||
|
||||
/**
|
||||
* Tests a get() on the fast backend, with no hit on the consistent backend.
|
||||
*/
|
||||
public function testGetDoesntHitConsistentBackend() {
|
||||
$consistent_cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
|
||||
$timestamp_cid = ChainedFastBackend::LAST_WRITE_TIMESTAMP_PREFIX . 'cache_foo';
|
||||
// Use the request time because that is what we will be comparing against.
|
||||
$timestamp_item = (object) array('cid' => $timestamp_cid, 'data' => (int) $_SERVER['REQUEST_TIME'] - 60);
|
||||
$consistent_cache->expects($this->once())
|
||||
->method('get')->with($timestamp_cid)
|
||||
->will($this->returnValue($timestamp_item));
|
||||
$consistent_cache->expects($this->never())
|
||||
->method('getMultiple');
|
||||
|
||||
$fast_cache = new MemoryBackend('foo');
|
||||
$fast_cache->set('foo', 'baz');
|
||||
|
||||
$chained_fast_backend = new ChainedFastBackend(
|
||||
$consistent_cache,
|
||||
$fast_cache,
|
||||
'foo'
|
||||
);
|
||||
$this->assertEquals('baz', $chained_fast_backend->get('foo')->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a fast cache miss gets data from the consistent cache backend.
|
||||
*/
|
||||
public function testFallThroughToConsistentCache() {
|
||||
$timestamp_item = (object) array(
|
||||
'cid' => ChainedFastBackend::LAST_WRITE_TIMESTAMP_PREFIX . 'cache_foo',
|
||||
'data' => time() + 60, // Time travel is easy.
|
||||
);
|
||||
$cache_item = (object) array(
|
||||
'cid' => 'foo',
|
||||
'data' => 'baz',
|
||||
'created' => time(),
|
||||
'expire' => time() + 3600,
|
||||
'tags' => ['tag'],
|
||||
);
|
||||
|
||||
$consistent_cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
|
||||
$fast_cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
|
||||
|
||||
// We should get a call for the timestamp on the consistent backend.
|
||||
$consistent_cache->expects($this->once())
|
||||
->method('get')
|
||||
->with($timestamp_item->cid)
|
||||
->will($this->returnValue($timestamp_item));
|
||||
|
||||
// We should get a call for the cache item on the consistent backend.
|
||||
$consistent_cache->expects($this->once())
|
||||
->method('getMultiple')
|
||||
->with(array($cache_item->cid))
|
||||
->will($this->returnValue(array($cache_item->cid => $cache_item)));
|
||||
|
||||
// We should get a call for the cache item on the fast backend.
|
||||
$fast_cache->expects($this->once())
|
||||
->method('getMultiple')
|
||||
->with(array($cache_item->cid))
|
||||
->will($this->returnValue(array($cache_item->cid => $cache_item)));
|
||||
|
||||
// We should get a call to set the cache item on the fast backend.
|
||||
$fast_cache->expects($this->once())
|
||||
->method('set')
|
||||
->with($cache_item->cid, $cache_item->data, $cache_item->expire);
|
||||
|
||||
$chained_fast_backend = new ChainedFastBackend(
|
||||
$consistent_cache,
|
||||
$fast_cache,
|
||||
'foo'
|
||||
);
|
||||
$this->assertEquals('baz', $chained_fast_backend->get('foo')->data);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,261 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Cache\Context\CacheContextsManagerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\Context\CacheContextsManager;
|
||||
use Drupal\Core\Cache\Context\CacheContextInterface;
|
||||
use Drupal\Core\Cache\Context\CalculatedCacheContextInterface;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Cache\Context\CacheContextsManager
|
||||
* @group Cache
|
||||
*/
|
||||
class CacheContextsManagerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @covers ::optimizeTokens
|
||||
*
|
||||
* @dataProvider providerTestOptimizeTokens
|
||||
*/
|
||||
public function testOptimizeTokens(array $context_tokens, array $optimized_context_tokens) {
|
||||
$container = $this->getMockBuilder('Drupal\Core\DependencyInjection\Container')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$container->expects($this->any())
|
||||
->method('get')
|
||||
->will($this->returnValueMap([
|
||||
['a', Container::EXCEPTION_ON_INVALID_REFERENCE, new FooCacheContext()],
|
||||
['a.b', Container::EXCEPTION_ON_INVALID_REFERENCE, new FooCacheContext()],
|
||||
['a.b.c', Container::EXCEPTION_ON_INVALID_REFERENCE, new BazCacheContext()],
|
||||
['x', Container::EXCEPTION_ON_INVALID_REFERENCE, new BazCacheContext()],
|
||||
]));
|
||||
$cache_contexts_manager = new CacheContextsManager($container, $this->getContextsFixture());
|
||||
|
||||
$this->assertSame($optimized_context_tokens, $cache_contexts_manager->optimizeTokens($context_tokens));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of context token sets.
|
||||
*/
|
||||
public function providerTestOptimizeTokens() {
|
||||
return [
|
||||
[['a', 'x'], ['a', 'x']],
|
||||
[['a.b', 'x'], ['a.b', 'x']],
|
||||
|
||||
// Direct ancestor, single-level hierarchy.
|
||||
[['a', 'a.b'], ['a']],
|
||||
[['a.b', 'a'], ['a']],
|
||||
|
||||
// Direct ancestor, multi-level hierarchy.
|
||||
[['a.b', 'a.b.c'], ['a.b']],
|
||||
[['a.b.c', 'a.b'], ['a.b']],
|
||||
|
||||
// Indirect ancestor.
|
||||
[['a', 'a.b.c'], ['a']],
|
||||
[['a.b.c', 'a'], ['a']],
|
||||
|
||||
// Direct & indirect ancestors.
|
||||
[['a', 'a.b', 'a.b.c'], ['a']],
|
||||
[['a', 'a.b.c', 'a.b'], ['a']],
|
||||
[['a.b', 'a', 'a.b.c'], ['a']],
|
||||
[['a.b', 'a.b.c', 'a'], ['a']],
|
||||
[['a.b.c', 'a.b', 'a'], ['a']],
|
||||
[['a.b.c', 'a', 'a.b'], ['a']],
|
||||
|
||||
// Using parameters.
|
||||
[['a', 'a.b.c:foo'], ['a']],
|
||||
[['a.b.c:foo', 'a'], ['a']],
|
||||
[['a.b.c:foo', 'a.b.c'], ['a.b.c']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::convertTokensToKeys
|
||||
*/
|
||||
public function testConvertTokensToKeys() {
|
||||
$container = $this->getMockContainer();
|
||||
$cache_contexts_manager = new CacheContextsManager($container, $this->getContextsFixture());
|
||||
|
||||
$new_keys = $cache_contexts_manager->convertTokensToKeys([
|
||||
'foo',
|
||||
'baz:parameterA',
|
||||
'baz:parameterB',
|
||||
]);
|
||||
|
||||
$expected = [
|
||||
'baz.cnenzrgreN',
|
||||
'baz.cnenzrgreO',
|
||||
'bar',
|
||||
];
|
||||
$this->assertEquals($expected, $new_keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::convertTokensToKeys
|
||||
*
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage "non-cache-context" is not a valid cache context ID.
|
||||
*/
|
||||
public function testInvalidContext() {
|
||||
$container = $this->getMockContainer();
|
||||
$cache_contexts_manager = new CacheContextsManager($container, $this->getContextsFixture());
|
||||
|
||||
$cache_contexts_manager->convertTokensToKeys(["non-cache-context"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::convertTokensToKeys
|
||||
*
|
||||
* @expectedException \Exception
|
||||
*
|
||||
* @dataProvider providerTestInvalidCalculatedContext
|
||||
*/
|
||||
public function testInvalidCalculatedContext($context_token) {
|
||||
$container = $this->getMockContainer();
|
||||
$cache_contexts_manager = new CacheContextsManager($container, $this->getContextsFixture());
|
||||
|
||||
$cache_contexts_manager->convertTokensToKeys([$context_token]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of invalid 'baz' cache contexts: the parameter is missing.
|
||||
*/
|
||||
public function providerTestInvalidCalculatedContext() {
|
||||
return [
|
||||
['baz'],
|
||||
['baz:'],
|
||||
];
|
||||
}
|
||||
|
||||
public function testAvailableContextStrings() {
|
||||
$cache_contexts_manager = new CacheContextsManager($this->getMockContainer(), $this->getContextsFixture());
|
||||
$contexts = $cache_contexts_manager->getAll();
|
||||
$this->assertEquals(array("foo", "baz"), $contexts);
|
||||
}
|
||||
|
||||
public function testAvailableContextLabels() {
|
||||
$container = $this->getMockContainer();
|
||||
$cache_contexts_manager = new CacheContextsManager($container, $this->getContextsFixture());
|
||||
$labels = $cache_contexts_manager->getLabels();
|
||||
$expected = array("foo" => "Foo");
|
||||
$this->assertEquals($expected, $labels);
|
||||
}
|
||||
|
||||
protected function getContextsFixture() {
|
||||
return array('foo', 'baz');
|
||||
}
|
||||
|
||||
protected function getMockContainer() {
|
||||
$container = $this->getMockBuilder('Drupal\Core\DependencyInjection\Container')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$container->expects($this->any())
|
||||
->method('get')
|
||||
->will($this->returnValueMap([
|
||||
['cache_context.foo', Container::EXCEPTION_ON_INVALID_REFERENCE, new FooCacheContext()],
|
||||
['cache_context.baz', Container::EXCEPTION_ON_INVALID_REFERENCE, new BazCacheContext()],
|
||||
]));
|
||||
return $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of cache context token arrays.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function validateTokensProvider() {
|
||||
return [
|
||||
[[], FALSE],
|
||||
[['foo'], FALSE],
|
||||
[['foo', 'foo.bar'], FALSE],
|
||||
[['foo', 'baz:llama'], FALSE],
|
||||
// Invalid.
|
||||
[[FALSE], 'Cache contexts must be strings, boolean given.'],
|
||||
[[TRUE], 'Cache contexts must be strings, boolean given.'],
|
||||
[['foo', FALSE], 'Cache contexts must be strings, boolean given.'],
|
||||
[[NULL], 'Cache contexts must be strings, NULL given.'],
|
||||
[['foo', NULL], 'Cache contexts must be strings, NULL given.'],
|
||||
[[1337], 'Cache contexts must be strings, integer given.'],
|
||||
[['foo', 1337], 'Cache contexts must be strings, integer given.'],
|
||||
[[3.14], 'Cache contexts must be strings, double given.'],
|
||||
[['foo', 3.14], 'Cache contexts must be strings, double given.'],
|
||||
[[[]], 'Cache contexts must be strings, array given.'],
|
||||
[['foo', []], 'Cache contexts must be strings, array given.'],
|
||||
[['foo', ['bar']], 'Cache contexts must be strings, array given.'],
|
||||
[[new \stdClass()], 'Cache contexts must be strings, object given.'],
|
||||
[['foo', new \stdClass()], 'Cache contexts must be strings, object given.'],
|
||||
// Non-existing.
|
||||
[['foo.bar', 'qux'], '"qux" is not a valid cache context ID.'],
|
||||
[['qux', 'baz'], '"qux" is not a valid cache context ID.'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::validateTokens
|
||||
*
|
||||
* @dataProvider validateTokensProvider
|
||||
*/
|
||||
public function testValidateContexts(array $contexts, $expected_exception_message) {
|
||||
$container = new ContainerBuilder();
|
||||
$cache_contexts_manager = new CacheContextsManager($container, ['foo', 'foo.bar', 'baz']);
|
||||
if ($expected_exception_message !== FALSE) {
|
||||
$this->setExpectedException('LogicException', $expected_exception_message);
|
||||
}
|
||||
// If it doesn't throw an exception, validateTokens() returns NULL.
|
||||
$this->assertNull($cache_contexts_manager->validateTokens($contexts));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fake cache context class.
|
||||
*/
|
||||
class FooCacheContext implements CacheContextInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getLabel() {
|
||||
return 'Foo';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContext() {
|
||||
return 'bar';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fake calculated cache context class.
|
||||
*/
|
||||
class BazCacheContext implements CalculatedCacheContextInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getLabel() {
|
||||
return 'Baz';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContext($parameter = NULL) {
|
||||
if (!is_string($parameter) || strlen($parameter) === 0) {
|
||||
throw new \Exception();
|
||||
}
|
||||
return 'baz.' . str_rot13($parameter);
|
||||
}
|
||||
|
||||
}
|
32
core/tests/Drupal/Tests/Core/Cache/NullBackendTest.php
Normal file
32
core/tests/Drupal/Tests/Core/Cache/NullBackendTest.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Cache\NullBackendTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Cache;
|
||||
|
||||
use Drupal\Core\Cache\NullBackend;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the cache NullBackend.
|
||||
*
|
||||
* @group Cache
|
||||
*/
|
||||
class NullBackendTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that the NullBackend does not actually store variables.
|
||||
*/
|
||||
function testNullBackend() {
|
||||
$null_cache = new NullBackend('test');
|
||||
|
||||
$key = $this->randomMachineName();
|
||||
$value = $this->randomMachineName();
|
||||
|
||||
$null_cache->set($key, $value);
|
||||
$this->assertFalse($null_cache->get($key));
|
||||
}
|
||||
}
|
74
core/tests/Drupal/Tests/Core/Common/AttributesTest.php
Normal file
74
core/tests/Drupal/Tests/Core/Common/AttributesTest.php
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Common\AttributesTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Common;
|
||||
|
||||
use Drupal\Core\Template\Attribute;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the Drupal\Core\Template\Attribute functionality.
|
||||
*
|
||||
* @group Common
|
||||
*/
|
||||
class AttributesTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Provides data for the Attribute test.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestAttributeData() {
|
||||
return array(
|
||||
// Verify that special characters are HTML encoded.
|
||||
array(array('&"\'<>' => 'value'), ' &"'<>="value"', 'HTML encode attribute names.'),
|
||||
array(array('title' => '&"\'<>'), ' title="&"'<>"', 'HTML encode attribute values.'),
|
||||
// Verify multi-value attributes are concatenated with spaces.
|
||||
array(array('class' => array('first', 'last')), ' class="first last"', 'Concatenate multi-value attributes.'),
|
||||
// Verify boolean attribute values are rendered correctly.
|
||||
array(array('disabled' => TRUE), ' disabled', 'Boolean attribute is rendered.'),
|
||||
array(array('disabled' => FALSE), '', 'Boolean attribute is not rendered.'),
|
||||
// Verify empty attribute values are rendered.
|
||||
array(array('alt' => ''), ' alt=""', 'Empty attribute value #1.'),
|
||||
array(array('alt' => NULL), '', 'Null attribute value #2.'),
|
||||
// Verify multiple attributes are rendered.
|
||||
array(
|
||||
array(
|
||||
'id' => 'id-test',
|
||||
'class' => array('first', 'last'),
|
||||
'alt' => 'Alternate',
|
||||
),
|
||||
' id="id-test" class="first last" alt="Alternate"',
|
||||
'Multiple attributes.'
|
||||
),
|
||||
// Verify empty attributes array is rendered.
|
||||
array(array(), '', 'Empty attributes array.'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests casting an Attribute object to a string.
|
||||
*
|
||||
* @see \Drupal\Core\Template\Attribute::__toString()
|
||||
*
|
||||
* @dataProvider providerTestAttributeData
|
||||
*/
|
||||
function testDrupalAttributes($attributes, $expected, $message) {
|
||||
$this->assertSame($expected, (string) new Attribute($attributes), $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test attribute iteration
|
||||
*/
|
||||
public function testAttributeIteration() {
|
||||
$attribute = new Attribute(array('key1' => 'value1'));
|
||||
foreach ($attribute as $value) {
|
||||
$this->assertSame((string) $value, 'value1', 'Iterate over attribute.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
77
core/tests/Drupal/Tests/Core/Common/DiffArrayTest.php
Normal file
77
core/tests/Drupal/Tests/Core/Common/DiffArrayTest.php
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Common\DiffArrayTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Common;
|
||||
|
||||
use Drupal\Component\Utility\DiffArray;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the DiffArray helper class.
|
||||
*
|
||||
* @group Common
|
||||
*/
|
||||
class DiffArrayTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Array to use for testing.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $array1;
|
||||
|
||||
/**
|
||||
* Array to use for testing.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $array2;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->array1 = array(
|
||||
'same' => 'yes',
|
||||
'different' => 'no',
|
||||
'array_empty_diff' => array(),
|
||||
'null' => NULL,
|
||||
'int_diff' => 1,
|
||||
'array_diff' => array('same' => 'same', 'array' => array('same' => 'same')),
|
||||
'array_compared_to_string' => array('value'),
|
||||
'string_compared_to_array' => 'value',
|
||||
'new' => 'new',
|
||||
);
|
||||
$this->array2 = array(
|
||||
'same' => 'yes',
|
||||
'different' => 'yes',
|
||||
'array_empty_diff' => array(),
|
||||
'null' => NULL,
|
||||
'int_diff' => '1',
|
||||
'array_diff' => array('same' => 'different', 'array' => array('same' => 'same')),
|
||||
'array_compared_to_string' => 'value',
|
||||
'string_compared_to_array' => array('value'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests DiffArray::diffAssocRecursive().
|
||||
*/
|
||||
public function testDiffAssocRecursive() {
|
||||
$expected = array(
|
||||
'different' => 'no',
|
||||
'int_diff' => 1,
|
||||
// The 'array' key should not be returned, as it's the same.
|
||||
'array_diff' => array('same' => 'same'),
|
||||
'array_compared_to_string' => array('value'),
|
||||
'string_compared_to_array' => 'value',
|
||||
'new' => 'new',
|
||||
);
|
||||
|
||||
$this->assertSame(DiffArray::diffAssocRecursive($this->array1, $this->array2), $expected);
|
||||
}
|
||||
|
||||
}
|
64
core/tests/Drupal/Tests/Core/Common/TagsTest.php
Normal file
64
core/tests/Drupal/Tests/Core/Common/TagsTest.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Common\TagsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Common;
|
||||
|
||||
use Drupal\Component\Utility\Tags;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests explosion and implosion of autocomplete tags.
|
||||
*
|
||||
* @group Common
|
||||
*/
|
||||
class TagsTest extends UnitTestCase {
|
||||
|
||||
protected $validTags = array(
|
||||
'Drupal' => 'Drupal',
|
||||
'Drupal with some spaces' => 'Drupal with some spaces',
|
||||
'"Legendary Drupal mascot of doom: ""Druplicon"""' => 'Legendary Drupal mascot of doom: "Druplicon"',
|
||||
'"Drupal, although it rhymes with sloopal, is as awesome as a troopal!"' => 'Drupal, although it rhymes with sloopal, is as awesome as a troopal!',
|
||||
);
|
||||
|
||||
/**
|
||||
* Explodes a series of tags.
|
||||
*/
|
||||
public function explodeTags() {
|
||||
$string = implode(', ', array_keys($this->validTags));
|
||||
$tags = Tags::explode($string);
|
||||
$this->assertTags($tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implodes a series of tags.
|
||||
*/
|
||||
public function testImplodeTags() {
|
||||
$tags = array_values($this->validTags);
|
||||
// Let's explode and implode to our heart's content.
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$string = Tags::implode($tags);
|
||||
$tags = Tags::explode($string);
|
||||
}
|
||||
$this->assertTags($tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function: asserts that the ending array of tags is what we wanted.
|
||||
*/
|
||||
protected function assertTags($tags) {
|
||||
$original = $this->validTags;
|
||||
foreach ($tags as $tag) {
|
||||
$key = array_search($tag, $original);
|
||||
$this->assertTrue((bool) $key, $tag, sprintf('Make sure tag %s shows up in the final tags array (originally %s)', $tag, $key));
|
||||
unset($original[$key]);
|
||||
}
|
||||
foreach ($original as $leftover) {
|
||||
$this->fail(sprintf('Leftover tag %s was left over.', $leftover));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Condition\ConditionAccessResolverTraitTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Condition;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\ContextException;
|
||||
use Drupal\Core\Condition\ConditionAccessResolverTrait;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Condition\ConditionAccessResolverTrait
|
||||
* @group Condition
|
||||
*/
|
||||
class ConditionAccessResolverTraitTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests the resolveConditions() method.
|
||||
*
|
||||
* @covers ::resolveConditions
|
||||
*
|
||||
* @dataProvider providerTestResolveConditions
|
||||
*/
|
||||
public function testResolveConditions($conditions, $logic, $expected) {
|
||||
$trait_object = new TestConditionAccessResolverTrait();
|
||||
$this->assertEquals($expected, $trait_object->resolveConditions($conditions, $logic));
|
||||
}
|
||||
|
||||
public function providerTestResolveConditions() {
|
||||
$data = array();
|
||||
|
||||
$condition_true = $this->getMock('Drupal\Core\Condition\ConditionInterface');
|
||||
$condition_true->expects($this->any())
|
||||
->method('execute')
|
||||
->will($this->returnValue(TRUE));
|
||||
$condition_false = $this->getMock('Drupal\Core\Condition\ConditionInterface');
|
||||
$condition_false->expects($this->any())
|
||||
->method('execute')
|
||||
->will($this->returnValue(FALSE));
|
||||
$condition_exception = $this->getMock('Drupal\Core\Condition\ConditionInterface');
|
||||
$condition_exception->expects($this->any())
|
||||
->method('execute')
|
||||
->will($this->throwException(new ContextException()));
|
||||
|
||||
$conditions = array();
|
||||
$data[] = array($conditions, 'and', TRUE);
|
||||
$data[] = array($conditions, 'or', FALSE);
|
||||
|
||||
$conditions = array($condition_false);
|
||||
$data[] = array($conditions, 'or', FALSE);
|
||||
$data[] = array($conditions, 'and', FALSE);
|
||||
|
||||
$conditions = array($condition_true);
|
||||
$data[] = array($conditions, 'or', TRUE);
|
||||
$data[] = array($conditions, 'and', TRUE);
|
||||
|
||||
$conditions = array($condition_true, $condition_false);
|
||||
$data[] = array($conditions, 'or', TRUE);
|
||||
$data[] = array($conditions, 'and', FALSE);
|
||||
|
||||
$conditions = array($condition_exception);
|
||||
$data[] = array($conditions, 'or', FALSE);
|
||||
$data[] = array($conditions, 'and', FALSE);
|
||||
|
||||
$conditions = array($condition_true, $condition_exception);
|
||||
$data[] = array($conditions, 'or', TRUE);
|
||||
$data[] = array($conditions, 'and', FALSE);
|
||||
|
||||
$conditions = array($condition_exception, $condition_true);
|
||||
$data[] = array($conditions, 'or', TRUE);
|
||||
$data[] = array($conditions, 'and', FALSE);
|
||||
|
||||
$conditions = array($condition_false, $condition_exception);
|
||||
$data[] = array($conditions, 'or', FALSE);
|
||||
$data[] = array($conditions, 'and', FALSE);
|
||||
|
||||
$conditions = array($condition_exception, $condition_false);
|
||||
$data[] = array($conditions, 'or', FALSE);
|
||||
$data[] = array($conditions, 'and', FALSE);
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestConditionAccessResolverTrait {
|
||||
use \Drupal\Core\Condition\ConditionAccessResolverTrait {
|
||||
resolveConditions as public;
|
||||
}
|
||||
}
|
46
core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php
Normal file
46
core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\CachedStorageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Core\Config\CachedStorage;
|
||||
use Drupal\Core\Cache\NullBackend;
|
||||
|
||||
/**
|
||||
* Tests the interaction of cache and file storage in CachedStorage.
|
||||
*
|
||||
* @group Config
|
||||
*/
|
||||
class CachedStorageTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Cache\CacheFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $cacheFactory;
|
||||
|
||||
/**
|
||||
* Test listAll static cache.
|
||||
*/
|
||||
public function testListAllStaticCache() {
|
||||
$prefix = __FUNCTION__;
|
||||
$storage = $this->getMock('Drupal\Core\Config\StorageInterface');
|
||||
|
||||
$response = array("$prefix." . $this->randomMachineName(), "$prefix." . $this->randomMachineName());
|
||||
$storage->expects($this->once())
|
||||
->method('listAll')
|
||||
->with($prefix)
|
||||
->will($this->returnValue($response));
|
||||
|
||||
$cache = new NullBackend(__FUNCTION__);
|
||||
|
||||
$cachedStorage = new CachedStorage($storage, $cache);
|
||||
$this->assertEquals($response, $cachedStorage->listAll($prefix));
|
||||
$this->assertEquals($response, $cachedStorage->listAll($prefix));
|
||||
}
|
||||
|
||||
}
|
97
core/tests/Drupal/Tests/Core/Config/ConfigFactoryTest.php
Normal file
97
core/tests/Drupal/Tests/Core/Config/ConfigFactoryTest.php
Normal file
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\ConfigFactoryTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config;
|
||||
|
||||
use Drupal\Core\Config\Config;
|
||||
use Drupal\Core\Config\ConfigFactory;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* @group Config
|
||||
* @coversDefaultClass \Drupal\Core\Config\ConfigFactory
|
||||
*/
|
||||
class ConfigFactoryTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Config factory under test.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigFactory
|
||||
*/
|
||||
protected $configFactory;
|
||||
|
||||
/**
|
||||
* Storage.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* Event Dispatcher.
|
||||
*
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* Typed Config.
|
||||
*
|
||||
* @var \Drupal\Core\Config\TypedConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $typedConfig;
|
||||
|
||||
/**
|
||||
* The mocked cache tags invalidator.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $cacheTagsInvalidator;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
$this->storage = $this->getMock('Drupal\Core\Config\StorageInterface');
|
||||
$this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
$this->typedConfig = $this->getMock('\Drupal\Core\Config\TypedConfigManagerInterface');
|
||||
$this->configFactory = new ConfigFactory($this->storage, $this->eventDispatcher, $this->typedConfig);
|
||||
|
||||
$this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('cache_tags.invalidator', $this->cacheTagsInvalidator);
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::rename
|
||||
*/
|
||||
public function testRename() {
|
||||
$old = new Config($this->randomMachineName(), $this->storage, $this->eventDispatcher, $this->typedConfig);
|
||||
$new = new Config($this->randomMachineName(), $this->storage, $this->eventDispatcher, $this->typedConfig);
|
||||
|
||||
$this->storage->expects($this->exactly(2))
|
||||
->method('readMultiple')
|
||||
->willReturnMap([
|
||||
[[$old->getName()], $old->getRawData()],
|
||||
[[$new->getName()], $new->getRawData()],
|
||||
]);
|
||||
|
||||
$this->cacheTagsInvalidator->expects($this->once())
|
||||
->method('invalidateTags')
|
||||
->with($old->getCacheTags());
|
||||
|
||||
$this->storage->expects($this->once())
|
||||
->method('rename')
|
||||
->with($old->getName(), $new->getName());
|
||||
|
||||
$this->configFactory->rename($old->getName(), $new->getName());
|
||||
}
|
||||
|
||||
}
|
538
core/tests/Drupal/Tests/Core/Config/ConfigTest.php
Normal file
538
core/tests/Drupal/Tests/Core/Config/ConfigTest.php
Normal file
|
@ -0,0 +1,538 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\ConfigTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Core\Config\Config;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
|
||||
/**
|
||||
* Tests the Config.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Config\Config
|
||||
*
|
||||
* @group Config
|
||||
*
|
||||
* @see \Drupal\Core\Config\Config
|
||||
*/
|
||||
class ConfigTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Config.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Storage.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* Event Dispatcher.
|
||||
*
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* Typed Config.
|
||||
*
|
||||
* @var \Drupal\Core\Config\TypedConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $typedConfig;
|
||||
|
||||
/**
|
||||
* The mocked cache tags invalidator.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $cacheTagsInvalidator;
|
||||
|
||||
public function setUp() {
|
||||
$this->storage = $this->getMock('Drupal\Core\Config\StorageInterface');
|
||||
$this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
$this->typedConfig = $this->getMock('\Drupal\Core\Config\TypedConfigManagerInterface');
|
||||
$this->config = new Config('config.test', $this->storage, $this->eventDispatcher, $this->typedConfig);
|
||||
$this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('cache_tags.invalidator', $this->cacheTagsInvalidator);
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setName
|
||||
* @dataProvider setNameProvider
|
||||
*/
|
||||
public function testSetName($name) {
|
||||
// Set the name.
|
||||
$this->config->setName($name);
|
||||
|
||||
// Check that the name has been set correctly.
|
||||
$this->assertEquals($name, $this->config->getName());
|
||||
|
||||
// Check that the name validates.
|
||||
// Should throw \Drupal\Core\Config\ConfigNameException if invalid.
|
||||
$this->config->validateName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides config names to test.
|
||||
*
|
||||
* @see \Drupal\Tests\Core\Config\ConfigTest::testSetName()
|
||||
*/
|
||||
public function setNameProvider() {
|
||||
return array(
|
||||
// Valid name with dot.
|
||||
array(
|
||||
'test.name',
|
||||
),
|
||||
// Maximum length.
|
||||
array(
|
||||
'test.' . str_repeat('a', Config::MAX_NAME_LENGTH - 5),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::isNew
|
||||
*/
|
||||
public function testIsNew() {
|
||||
// Config should be new by default.
|
||||
$this->assertTrue($this->config->isNew());
|
||||
|
||||
// Config is no longer new once saved.
|
||||
$this->config->save();
|
||||
$this->assertFalse($this->config->isNew());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setData
|
||||
* @dataProvider nestedDataProvider
|
||||
*/
|
||||
public function testSetData($data) {
|
||||
$this->config->setData($data);
|
||||
$this->assertEquals($data, $this->config->getRawData());
|
||||
$this->assertConfigDataEquals($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
* @dataProvider nestedDataProvider
|
||||
*/
|
||||
public function testSaveNew($data) {
|
||||
$this->cacheTagsInvalidator->expects($this->never())
|
||||
->method('invalidateTags');
|
||||
|
||||
// Set initial data.
|
||||
$this->config->setData($data);
|
||||
|
||||
// Check that original data has not been set yet.
|
||||
foreach ($data as $key => $value) {
|
||||
$this->assertNull($this->config->getOriginal($key, FALSE));
|
||||
}
|
||||
|
||||
// Save so that the original data is set.
|
||||
$config = $this->config->save();
|
||||
|
||||
// Check that returned $config is instance of Config.
|
||||
$this->assertInstanceOf('\Drupal\Core\Config\Config', $config);
|
||||
|
||||
// Check that the original data it saved.
|
||||
$this->assertOriginalConfigDataEquals($data, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
* @dataProvider nestedDataProvider
|
||||
*/
|
||||
public function testSaveExisting($data) {
|
||||
$this->cacheTagsInvalidator->expects($this->once())
|
||||
->method('invalidateTags')
|
||||
->with(['config:config.test']);
|
||||
|
||||
// Set initial data.
|
||||
$this->config->setData($data);
|
||||
$this->config->save();
|
||||
|
||||
// Update.
|
||||
$new_data = $data;
|
||||
$new_data['a']['d'] = 2;
|
||||
$this->config->setData($new_data);
|
||||
$this->config->save();
|
||||
$this->assertOriginalConfigDataEquals($new_data, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setModuleOverride
|
||||
* @covers ::setSettingsOverride
|
||||
* @covers ::getOriginal
|
||||
* @dataProvider overrideDataProvider
|
||||
*/
|
||||
public function testOverrideData($data, $module_data, $setting_data) {
|
||||
// Set initial data.
|
||||
$this->config->setData($data);
|
||||
|
||||
// Check original data was set correctly.
|
||||
$this->assertConfigDataEquals($data);
|
||||
|
||||
// Save so that the original data is stored.
|
||||
$this->config->save();
|
||||
|
||||
// Set module override data and check value before and after save.
|
||||
$this->config->setModuleOverride($module_data);
|
||||
$this->assertConfigDataEquals($module_data);
|
||||
$this->config->save();
|
||||
$this->assertConfigDataEquals($module_data);
|
||||
|
||||
// Set setting override data and check value before and after save.
|
||||
$this->config->setSettingsOverride($setting_data);
|
||||
$this->assertConfigDataEquals($setting_data);
|
||||
$this->config->save();
|
||||
$this->assertConfigDataEquals($setting_data);
|
||||
|
||||
// Set module overrides again to ensure override order is correct.
|
||||
$this->config->setModuleOverride($module_data);
|
||||
|
||||
// Setting data should be overriding module data.
|
||||
$this->assertConfigDataEquals($setting_data);
|
||||
$this->config->save();
|
||||
$this->assertConfigDataEquals($setting_data);
|
||||
|
||||
// Check original data has not changed.
|
||||
$this->assertOriginalConfigDataEquals($data, FALSE);
|
||||
|
||||
// Check setting overrides are returned with $apply_overrides = TRUE.
|
||||
$this->assertOriginalConfigDataEquals($setting_data, TRUE);
|
||||
|
||||
// Check that $apply_overrides defaults to TRUE.
|
||||
foreach ($setting_data as $key => $value) {
|
||||
$config_value = $this->config->getOriginal($key);
|
||||
$this->assertEquals($value, $config_value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::set
|
||||
* @dataProvider nestedDataProvider
|
||||
*/
|
||||
public function testSetValue($data) {
|
||||
foreach ($data as $key => $value) {
|
||||
$this->config->set($key, $value);
|
||||
}
|
||||
$this->assertConfigDataEquals($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::set
|
||||
* @expectedException \Drupal\Core\Config\ConfigValueException
|
||||
*/
|
||||
public function testSetValidation() {
|
||||
$this->config->set('testData', array('dot.key' => 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::set
|
||||
* @expectedException PHPUnit_Framework_Error_Warning
|
||||
*/
|
||||
public function testSetIllegalOffsetValue() {
|
||||
// Set a single value.
|
||||
$this->config->set('testData', 1);
|
||||
|
||||
// Attempt to treat the single value as a nested item.
|
||||
$this->config->set('testData.illegalOffset', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::initWithData
|
||||
* @dataProvider nestedDataProvider
|
||||
*/
|
||||
public function testInitWithData($data) {
|
||||
$config = $this->config->initWithData($data);
|
||||
|
||||
// Should return the Config object.
|
||||
$this->assertInstanceOf('\Drupal\Core\Config\Config', $config);
|
||||
|
||||
// Check config is not new.
|
||||
$this->assertEquals(FALSE, $this->config->isNew());
|
||||
|
||||
// Check that data value was set correctly.
|
||||
$this->assertConfigDataEquals($data);
|
||||
|
||||
// Check that original data was set.
|
||||
$this->assertOriginalConfigDataEquals($data, TRUE);
|
||||
|
||||
// Check without applying overrides.
|
||||
$this->assertOriginalConfigDataEquals($data, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::clear
|
||||
* @dataProvider simpleDataProvider
|
||||
*/
|
||||
public function testClear($data) {
|
||||
foreach ($data as $key => $value) {
|
||||
// Check that values are cleared.
|
||||
$this->config->set($key, $value);
|
||||
$this->assertEquals($value, $this->config->get($key));
|
||||
$this->config->clear($key);
|
||||
$this->assertNull($this->config->get($key));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::clear
|
||||
* @dataProvider nestedDataProvider
|
||||
*/
|
||||
public function testNestedClear($data) {
|
||||
foreach ($data as $key => $value) {
|
||||
// Check that values are cleared.
|
||||
$this->config->set($key, $value);
|
||||
// Check each nested value.
|
||||
foreach ($value as $nested_key => $nested_value) {
|
||||
$full_nested_key = $key . '.' . $nested_key;
|
||||
$this->assertEquals($nested_value, $this->config->get($full_nested_key));
|
||||
$this->config->clear($full_nested_key);
|
||||
$this->assertNull($this->config->get($full_nested_key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::delete
|
||||
* @dataProvider overrideDataProvider
|
||||
*/
|
||||
public function testDelete($data, $module_data) {
|
||||
$this->cacheTagsInvalidator->expects($this->once())
|
||||
->method('invalidateTags')
|
||||
->with(['config:config.test']);
|
||||
|
||||
// Set initial data.
|
||||
foreach ($data as $key => $value) {
|
||||
$this->config->set($key, $value);
|
||||
}
|
||||
// Set overrides.
|
||||
$this->config->setModuleOverride($module_data);
|
||||
|
||||
// Save.
|
||||
$this->config->save();
|
||||
|
||||
// Check that original data is still correct.
|
||||
$this->assertOriginalConfigDataEquals($data, FALSE);
|
||||
|
||||
// Check overrides have been set.
|
||||
$this->assertConfigDataEquals($module_data);
|
||||
$this->assertOriginalConfigDataEquals($module_data, TRUE);
|
||||
|
||||
// Check that config is new.
|
||||
$this->assertFalse($this->config->isNew());
|
||||
|
||||
// Delete.
|
||||
$this->config->delete();
|
||||
|
||||
// Check object properties have been reset.
|
||||
$this->assertTrue($this->config->isNew());
|
||||
foreach ($data as $key => $value) {
|
||||
$this->assertEmpty($this->config->getOriginal($key, FALSE));
|
||||
}
|
||||
|
||||
// Check that overrides have persisted.
|
||||
foreach ($module_data as $key => $value) {
|
||||
$this->assertConfigDataEquals($module_data);
|
||||
$this->assertOriginalConfigDataEquals($module_data, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::merge
|
||||
* @dataProvider mergeDataProvider
|
||||
*/
|
||||
public function testMerge($data, $data_to_merge, $merged_data) {
|
||||
// Set initial data.
|
||||
$this->config->setData($data);
|
||||
|
||||
// Data to merge.
|
||||
$this->config->merge($data_to_merge);
|
||||
|
||||
// Check that data has merged correctly.
|
||||
$this->assertEquals($merged_data, $this->config->getRawData());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data to test merges.
|
||||
*
|
||||
* @see \Drupal\Tests\Core\Config\ConfigTest::testMerge()
|
||||
*/
|
||||
public function mergeDataProvider() {
|
||||
return array(
|
||||
array(
|
||||
// Data.
|
||||
array('a' => 1, 'b' => 2, 'c' => array('d' => 3)),
|
||||
// Data to merge.
|
||||
array('a' => 2, 'e' => 4, 'c' => array('f' => 5)),
|
||||
// Data merged.
|
||||
array('a' => 2, 'b' => 2, 'c' => array('d' => 3, 'f' => 5), 'e' => 4),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::validateName
|
||||
* @expectedException \Drupal\Core\Config\ConfigNameException
|
||||
* @dataProvider validateNameProvider
|
||||
*/
|
||||
public function testValidateNameException($name, $exception_message) {
|
||||
$this->setExpectedException('\Drupal\Core\Config\ConfigNameException', $exception_message);
|
||||
$this->config->validateName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getCacheTags
|
||||
*/
|
||||
public function testGetCacheTags() {
|
||||
$this->assertSame(['config:' . $this->config->getName()], $this->config->getCacheTags());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data to test name validation.
|
||||
*
|
||||
* @see \Drupal\Tests\Core\Config\ConfigTest::testValidateNameException()
|
||||
*/
|
||||
public function validateNameProvider() {
|
||||
$return = array(
|
||||
// Name missing namespace (dot).
|
||||
array(
|
||||
'MissingNamespace',
|
||||
SafeMarkup::format('Missing namespace in Config object name MissingNamespace.', array(
|
||||
'@name' => 'MissingNamespace',
|
||||
)),
|
||||
),
|
||||
// Exceeds length (max length plus an extra dot).
|
||||
array(
|
||||
str_repeat('a', Config::MAX_NAME_LENGTH) . ".",
|
||||
SafeMarkup::format('Config object name @name exceeds maximum allowed length of @length characters.', array(
|
||||
'@name' => str_repeat('a', Config::MAX_NAME_LENGTH) . ".",
|
||||
'@length' => Config::MAX_NAME_LENGTH,
|
||||
)),
|
||||
),
|
||||
);
|
||||
// Name must not contain : ? * < > " ' / \
|
||||
foreach (array(':', '?', '*', '<', '>', '"', "'", '/', '\\') as $char) {
|
||||
$name = 'name.' . $char;
|
||||
$return[] = array(
|
||||
$name,
|
||||
SafeMarkup::format('Invalid character in Config object name @name.', array(
|
||||
'@name' => $name,
|
||||
)),
|
||||
);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides override data.
|
||||
*
|
||||
* @see \Drupal\Tests\Core\Config\ConfigTest::testOverrideData()
|
||||
* @see \Drupal\Tests\Core\Config\ConfigTest::testDelete()
|
||||
*/
|
||||
public function overrideDataProvider() {
|
||||
return array(
|
||||
array(
|
||||
// Original data.
|
||||
array(
|
||||
'a' => 'originalValue',
|
||||
),
|
||||
// Module overrides.
|
||||
array(
|
||||
'a' => 'moduleValue',
|
||||
),
|
||||
// Setting overrides.
|
||||
array(
|
||||
'a' => 'settingValue',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides simple test data.
|
||||
*
|
||||
* @see \Drupal\Tests\Core\Config\ConfigTest::testClear()
|
||||
*/
|
||||
public function simpleDataProvider() {
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
'a' => '1',
|
||||
'b' => '2',
|
||||
'c' => '3',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides nested test data.
|
||||
*
|
||||
* @see \Drupal\Tests\Core\Config\ConfigTest::testSetData()
|
||||
* @see \Drupal\Tests\Core\Config\ConfigTest::testSave()
|
||||
* @see \Drupal\Tests\Core\Config\ConfigTest::testSetValue()
|
||||
* @see \Drupal\Tests\Core\Config\ConfigTest::testInitWithData()
|
||||
* @see \Drupal\Tests\Core\Config\ConfigTest::testNestedClear()
|
||||
*/
|
||||
public function nestedDataProvider() {
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
'a' => array(
|
||||
'd' => 1,
|
||||
),
|
||||
'b' => array(
|
||||
'e' => 2,
|
||||
),
|
||||
'c' => array(
|
||||
'f' => 3,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts all config data equals $data provided.
|
||||
*
|
||||
* @param array $data
|
||||
* Config data to be checked.
|
||||
*/
|
||||
public function assertConfigDataEquals($data) {
|
||||
foreach ($data as $key => $value) {
|
||||
$this->assertEquals($value, $this->config->get($key));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts all original config data equals $data provided.
|
||||
*
|
||||
* @param array $data
|
||||
* Config data to be checked.
|
||||
* @param bool $apply_overrides
|
||||
* Apply any overrides to the original data.
|
||||
*/
|
||||
public function assertOriginalConfigDataEquals($data, $apply_overrides) {
|
||||
foreach ($data as $key => $value) {
|
||||
$config_value = $this->config->getOriginal($key, $apply_overrides);
|
||||
$this->assertEquals($value, $config_value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\Entity\ConfigDependencyManagerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config\Entity;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Core\Config\Entity\ConfigDependencyManager;
|
||||
|
||||
/**
|
||||
* Tests the ConfigDependencyManager class.
|
||||
*
|
||||
* @group Config
|
||||
*/
|
||||
class ConfigDependencyManagerTest extends UnitTestCase {
|
||||
|
||||
public function testNoConfiguration() {
|
||||
$dep_manger = new ConfigDependencyManager();
|
||||
$this->assertEmpty($dep_manger->getDependentEntities('config', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84'));
|
||||
}
|
||||
|
||||
public function testNoConfigEntities() {
|
||||
$dep_manger = new ConfigDependencyManager();
|
||||
$dep_manger->setData(array(
|
||||
'simple.config' => array(
|
||||
'key' => 'value',
|
||||
),
|
||||
));
|
||||
$this->assertEmpty($dep_manger->getDependentEntities('config', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84'));
|
||||
|
||||
// Configuration is always dependent on its provider.
|
||||
$dependencies = $dep_manger->getDependentEntities('module', 'simple');
|
||||
$this->assertArrayHasKey('simple.config', $dependencies);
|
||||
$this->assertCount(1, $dependencies);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,563 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\Entity\ConfigEntityBaseUnitTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config\Entity;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Tests\Core\Plugin\Fixtures\TestConfigurablePlugin;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Config\Entity\ConfigEntityBase
|
||||
* @group Config
|
||||
*/
|
||||
class ConfigEntityBaseUnitTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The entity under test.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Entity\ConfigEntityBase|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* The entity type used for testing.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Entity\ConfigEntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entityType;
|
||||
|
||||
/**
|
||||
* The entity manager used for testing.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* The ID of the type of the entity under test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $entityTypeId;
|
||||
|
||||
/**
|
||||
* The UUID generator used for testing.
|
||||
*
|
||||
* @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $uuid;
|
||||
|
||||
/**
|
||||
* The provider of the entity type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $provider;
|
||||
|
||||
/**
|
||||
* The language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The entity ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* The mocked cache backend.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $cacheTagsInvalidator;
|
||||
|
||||
/**
|
||||
* The mocked typed config manager.
|
||||
*
|
||||
* @var \Drupal\Core\Config\TypedConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $typedConfigManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->id = $this->randomMachineName();
|
||||
$values = array(
|
||||
'id' => $this->id,
|
||||
'langcode' => 'en',
|
||||
'uuid' => '3bb9ee60-bea5-4622-b89b-a63319d10b3a',
|
||||
);
|
||||
$this->entityTypeId = $this->randomMachineName();
|
||||
$this->provider = $this->randomMachineName();
|
||||
$this->entityType = $this->getMock('\Drupal\Core\Config\Entity\ConfigEntityTypeInterface');
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getProvider')
|
||||
->will($this->returnValue($this->provider));
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getConfigPrefix')
|
||||
->willReturn('test_provider.' . $this->entityTypeId);
|
||||
|
||||
$this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
|
||||
$this->entityManager->expects($this->any())
|
||||
->method('getDefinition')
|
||||
->with($this->entityTypeId)
|
||||
->will($this->returnValue($this->entityType));
|
||||
|
||||
$this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
|
||||
|
||||
$this->languageManager = $this->getMock('\Drupal\Core\Language\LanguageManagerInterface');
|
||||
$this->languageManager->expects($this->any())
|
||||
->method('getLanguage')
|
||||
->with('en')
|
||||
->will($this->returnValue(new Language(array('id' => 'en'))));
|
||||
|
||||
$this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
|
||||
|
||||
$this->typedConfigManager = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface');
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('entity.manager', $this->entityManager);
|
||||
$container->set('uuid', $this->uuid);
|
||||
$container->set('language_manager', $this->languageManager);
|
||||
$container->set('cache_tags.invalidator', $this->cacheTagsInvalidator);
|
||||
$container->set('config.typed', $this->typedConfigManager);
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$this->entity = $this->getMockForAbstractClass('\Drupal\Core\Config\Entity\ConfigEntityBase', array($values, $this->entityTypeId));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::calculateDependencies
|
||||
*/
|
||||
public function testCalculateDependencies() {
|
||||
// Calculating dependencies will reset the dependencies array.
|
||||
$this->entity->set('dependencies', array('module' => array('node')));
|
||||
$this->assertEmpty($this->entity->calculateDependencies());
|
||||
|
||||
// Calculating dependencies will reset the dependencies array using enforced
|
||||
// dependencies.
|
||||
$this->entity->set('dependencies', array('module' => array('node'), 'enforced' => array('module' => 'views')));
|
||||
$dependencies = $this->entity->calculateDependencies();
|
||||
$this->assertContains('views', $dependencies['module']);
|
||||
$this->assertNotContains('node', $dependencies['module']);
|
||||
$this->assertContains('views', $dependencies['enforced']['module']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::preSave
|
||||
*/
|
||||
public function testPreSaveDuringSync() {
|
||||
$query = $this->getMock('\Drupal\Core\Entity\Query\QueryInterface');
|
||||
$storage = $this->getMock('\Drupal\Core\Config\Entity\ConfigEntityStorageInterface');
|
||||
|
||||
$query->expects($this->any())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array()));
|
||||
$query->expects($this->any())
|
||||
->method('condition')
|
||||
->will($this->returnValue($query));
|
||||
$storage->expects($this->any())
|
||||
->method('getQuery')
|
||||
->will($this->returnValue($query));
|
||||
$storage->expects($this->any())
|
||||
->method('loadUnchanged')
|
||||
->will($this->returnValue($this->entity));
|
||||
|
||||
// Saving an entity will not reset the dependencies array during config
|
||||
// synchronization.
|
||||
$this->entity->set('dependencies', array('module' => array('node')));
|
||||
$this->entity->preSave($storage);
|
||||
$this->assertEmpty($this->entity->getDependencies());
|
||||
|
||||
$this->entity->setSyncing(TRUE);
|
||||
$this->entity->set('dependencies', array('module' => array('node')));
|
||||
$this->entity->preSave($storage);
|
||||
$dependencies = $this->entity->getDependencies();
|
||||
$this->assertContains('node', $dependencies['module']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::addDependency
|
||||
*/
|
||||
public function testAddDependency() {
|
||||
$method = new \ReflectionMethod('\Drupal\Core\Config\Entity\ConfigEntityBase', 'addDependency');
|
||||
$method->setAccessible(TRUE);
|
||||
$method->invoke($this->entity, 'module', $this->provider);
|
||||
$method->invoke($this->entity, 'module', 'core');
|
||||
$method->invoke($this->entity, 'module', 'node');
|
||||
$dependencies = $this->entity->getDependencies();
|
||||
$this->assertNotContains($this->provider, $dependencies['module']);
|
||||
$this->assertNotContains('core', $dependencies['module']);
|
||||
$this->assertContains('node', $dependencies['module']);
|
||||
|
||||
// Test sorting of dependencies.
|
||||
$method->invoke($this->entity, 'module', 'action');
|
||||
$dependencies = $this->entity->getDependencies();
|
||||
$this->assertEquals(array('action', 'node'), $dependencies['module']);
|
||||
|
||||
// Test sorting of dependency types.
|
||||
$method->invoke($this->entity, 'entity', 'system.action.id');
|
||||
$dependencies = $this->entity->getDependencies();
|
||||
$this->assertEquals(array('entity', 'module'), array_keys($dependencies));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::calculateDependencies
|
||||
*
|
||||
* @dataProvider providerCalculateDependenciesWithPluginCollections
|
||||
*/
|
||||
public function testCalculateDependenciesWithPluginCollections($definition, $expected_dependencies) {
|
||||
$values = array();
|
||||
$this->entity = $this->getMockBuilder('\Drupal\Tests\Core\Config\Entity\Fixtures\ConfigEntityBaseWithPluginCollections')
|
||||
->setConstructorArgs(array($values, $this->entityTypeId))
|
||||
->setMethods(array('getPluginCollections'))
|
||||
->getMock();
|
||||
|
||||
// Create a configurable plugin that would add a dependency.
|
||||
$instance_id = $this->randomMachineName();
|
||||
$instance = new TestConfigurablePlugin(array(), $instance_id, $definition);
|
||||
|
||||
// Create a plugin collection to contain the instance.
|
||||
$pluginCollection = $this->getMockBuilder('\Drupal\Core\Plugin\DefaultLazyPluginCollection')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('get'))
|
||||
->getMock();
|
||||
$pluginCollection->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->with($instance_id)
|
||||
->will($this->returnValue($instance));
|
||||
$pluginCollection->addInstanceId($instance_id);
|
||||
|
||||
// Return the mocked plugin collection.
|
||||
$this->entity->expects($this->once())
|
||||
->method('getPluginCollections')
|
||||
->will($this->returnValue(array($pluginCollection)));
|
||||
|
||||
$this->assertEquals($expected_dependencies, $this->entity->calculateDependencies());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testCalculateDependenciesWithPluginCollections.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerCalculateDependenciesWithPluginCollections() {
|
||||
// Start with 'a' so that order of the dependency array is fixed.
|
||||
$instance_dependency_1 = 'a' . $this->randomMachineName(10);
|
||||
$instance_dependency_2 = 'a' . $this->randomMachineName(11);
|
||||
|
||||
return array(
|
||||
// Tests that the plugin provider is a module dependency.
|
||||
array(
|
||||
array('provider' => 'test'),
|
||||
array('module' => array('test')),
|
||||
),
|
||||
// Tests that a plugin that is provided by the same module as the config
|
||||
// entity is not added to the dependencies array.
|
||||
array(
|
||||
array('provider' => $this->provider),
|
||||
array('module' => array(NULL)),
|
||||
),
|
||||
// Tests that a config entity that has a plugin which provides config
|
||||
// dependencies in its definition has them.
|
||||
array(
|
||||
array(
|
||||
'provider' => 'test',
|
||||
'config_dependencies' => array(
|
||||
'config' => array($instance_dependency_1),
|
||||
'module' => array($instance_dependency_2),
|
||||
)
|
||||
),
|
||||
array(
|
||||
'config' => array($instance_dependency_1),
|
||||
'module' => array($instance_dependency_2, 'test')
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::calculateDependencies
|
||||
* @covers ::onDependencyRemoval
|
||||
*/
|
||||
public function testCalculateDependenciesWithThirdPartySettings() {
|
||||
$this->entity = $this->getMockForAbstractClass('\Drupal\Core\Config\Entity\ConfigEntityBase', array(array(), $this->entityTypeId));
|
||||
$this->entity->setThirdPartySetting('test_provider', 'test', 'test');
|
||||
$this->entity->setThirdPartySetting('test_provider2', 'test', 'test');
|
||||
$this->entity->setThirdPartySetting($this->provider, 'test', 'test');
|
||||
|
||||
$this->assertEquals(array('test_provider', 'test_provider2'), $this->entity->calculateDependencies()['module']);
|
||||
$changed = $this->entity->onDependencyRemoval(['module' => ['test_provider2']]);
|
||||
$this->assertTrue($changed, 'Calling onDependencyRemoval with an existing third party dependency provider returns TRUE.');
|
||||
$changed = $this->entity->onDependencyRemoval(['module' => ['test_provider3']]);
|
||||
$this->assertFalse($changed, 'Calling onDependencyRemoval with a non-existing third party dependency provider returns FALSE.');
|
||||
$this->assertEquals(array('test_provider'), $this->entity->calculateDependencies()['module']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setOriginalId
|
||||
* @covers ::getOriginalId
|
||||
*/
|
||||
public function testGetOriginalId() {
|
||||
$new_id = $this->randomMachineName();
|
||||
$this->entity->set('id', $new_id);
|
||||
$this->assertSame($this->id, $this->entity->getOriginalId());
|
||||
$this->assertSame($this->entity, $this->entity->setOriginalId($new_id));
|
||||
$this->assertSame($new_id, $this->entity->getOriginalId());
|
||||
|
||||
// Check that setOriginalId() does not change the entity "isNew" status.
|
||||
$this->assertFalse($this->entity->isNew());
|
||||
$this->entity->setOriginalId($this->randomMachineName());
|
||||
$this->assertFalse($this->entity->isNew());
|
||||
$this->entity->enforceIsNew();
|
||||
$this->assertTrue($this->entity->isNew());
|
||||
$this->entity->setOriginalId($this->randomMachineName());
|
||||
$this->assertTrue($this->entity->isNew());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::isNew
|
||||
*/
|
||||
public function testIsNew() {
|
||||
$this->assertFalse($this->entity->isNew());
|
||||
$this->assertSame($this->entity, $this->entity->enforceIsNew());
|
||||
$this->assertTrue($this->entity->isNew());
|
||||
$this->entity->enforceIsNew(FALSE);
|
||||
$this->assertFalse($this->entity->isNew());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::set
|
||||
* @covers ::get
|
||||
*/
|
||||
public function testGet() {
|
||||
$name = 'id';
|
||||
$value = $this->randomMachineName();
|
||||
$this->assertSame($this->id, $this->entity->get($name));
|
||||
$this->assertSame($this->entity, $this->entity->set($name, $value));
|
||||
$this->assertSame($value, $this->entity->get($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setStatus
|
||||
* @covers ::status
|
||||
*/
|
||||
public function testSetStatus() {
|
||||
$this->assertTrue($this->entity->status());
|
||||
$this->assertSame($this->entity, $this->entity->setStatus(FALSE));
|
||||
$this->assertFalse($this->entity->status());
|
||||
$this->entity->setStatus(TRUE);
|
||||
$this->assertTrue($this->entity->status());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::enable
|
||||
* @depends testSetStatus
|
||||
*/
|
||||
public function testEnable() {
|
||||
$this->entity->setStatus(FALSE);
|
||||
$this->assertSame($this->entity, $this->entity->enable());
|
||||
$this->assertTrue($this->entity->status());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::disable
|
||||
* @depends testSetStatus
|
||||
*/
|
||||
public function testDisable() {
|
||||
$this->cacheTagsInvalidator->expects($this->once())
|
||||
->method('invalidateTags')
|
||||
->with(array('config:test_provider.' . $this->entityTypeId . '.' . $this->id));
|
||||
|
||||
$this->entity->setStatus(TRUE);
|
||||
$this->assertSame($this->entity, $this->entity->disable());
|
||||
$this->assertFalse($this->entity->status());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setSyncing
|
||||
* @covers ::isSyncing
|
||||
*/
|
||||
public function testIsSyncing() {
|
||||
$this->assertFalse($this->entity->isSyncing());
|
||||
$this->assertSame($this->entity, $this->entity->setSyncing(TRUE));
|
||||
$this->assertTrue($this->entity->isSyncing());
|
||||
$this->entity->setSyncing(FALSE);
|
||||
$this->assertFalse($this->entity->isSyncing());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::createDuplicate
|
||||
*/
|
||||
public function testCreateDuplicate() {
|
||||
$this->entityType->expects($this->at(0))
|
||||
->method('getKey')
|
||||
->with('id')
|
||||
->will($this->returnValue('id'));
|
||||
|
||||
$this->entityType->expects($this->at(1))
|
||||
->method('hasKey')
|
||||
->with('uuid')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$this->entityType->expects($this->at(2))
|
||||
->method('getKey')
|
||||
->with('uuid')
|
||||
->will($this->returnValue('uuid'));
|
||||
|
||||
$new_uuid = '8607ef21-42bc-4913-978f-8c06207b0395';
|
||||
$this->uuid->expects($this->once())
|
||||
->method('generate')
|
||||
->will($this->returnValue($new_uuid));
|
||||
|
||||
$duplicate = $this->entity->createDuplicate();
|
||||
$this->assertInstanceOf('\Drupal\Core\Entity\Entity', $duplicate);
|
||||
$this->assertNotSame($this->entity, $duplicate);
|
||||
$this->assertFalse($this->entity->isNew());
|
||||
$this->assertTrue($duplicate->isNew());
|
||||
$this->assertNull($duplicate->id());
|
||||
$this->assertNull($duplicate->getOriginalId());
|
||||
$this->assertNotEquals($this->entity->uuid(), $duplicate->uuid());
|
||||
$this->assertSame($new_uuid, $duplicate->uuid());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::sort
|
||||
*/
|
||||
public function testSort() {
|
||||
$this->entityManager->expects($this->any())
|
||||
->method('getDefinition')
|
||||
->with($this->entityTypeId)
|
||||
->will($this->returnValue(array(
|
||||
'entity_keys' => array(
|
||||
'label' => 'label',
|
||||
),
|
||||
)));
|
||||
$entity_a = $this->entity;
|
||||
$entity_a->label = 'foo';
|
||||
$entity_b = clone $this->entity;
|
||||
$entity_b->label = 'bar';
|
||||
$list = array($entity_a, $entity_b);
|
||||
// Suppress errors because of https://bugs.php.net/bug.php?id=50688.
|
||||
@usort($list, '\Drupal\Core\Config\Entity\ConfigEntityBase::sort');
|
||||
$this->assertSame($entity_b, $list[0]);
|
||||
$entity_a->weight = 0;
|
||||
$entity_b->weight = 1;
|
||||
// Suppress errors because of https://bugs.php.net/bug.php?id=50688.
|
||||
@usort($list, array($entity_a, 'sort'));
|
||||
$this->assertSame($entity_a, $list[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::toArray
|
||||
*/
|
||||
public function testToArray() {
|
||||
$this->typedConfigManager->expects($this->never())
|
||||
->method('getDefinition');
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getPropertiesToExport')
|
||||
->willReturn(['id' => 'configId', 'dependencies' => 'dependencies']);
|
||||
$properties = $this->entity->toArray();
|
||||
$this->assertInternalType('array', $properties);
|
||||
$this->assertEquals(array('configId' => $this->entity->id(), 'dependencies' => array()), $properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::toArray
|
||||
*/
|
||||
public function testToArrayIdKey() {
|
||||
$entity = $this->getMockForAbstractClass('\Drupal\Core\Config\Entity\ConfigEntityBase', [[], $this->entityTypeId], '', TRUE, TRUE, TRUE, ['id', 'get']);
|
||||
$entity->expects($this->atLeastOnce())
|
||||
->method('id')
|
||||
->willReturn($this->id);
|
||||
$entity->expects($this->once())
|
||||
->method('get')
|
||||
->with('dependencies')
|
||||
->willReturn([]);
|
||||
$this->typedConfigManager->expects($this->never())
|
||||
->method('getDefinition');
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getPropertiesToExport')
|
||||
->willReturn(['id' => 'configId', 'dependencies' => 'dependencies']);
|
||||
$this->entityType->expects($this->once())
|
||||
->method('getKey')
|
||||
->with('id')
|
||||
->willReturn('id');
|
||||
$properties = $entity->toArray();
|
||||
$this->assertInternalType('array', $properties);
|
||||
$this->assertEquals(['configId' => $entity->id(), 'dependencies' => []], $properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::toArray
|
||||
*/
|
||||
public function testToArraySchemaFallback() {
|
||||
$this->typedConfigManager->expects($this->once())
|
||||
->method('getDefinition')
|
||||
->will($this->returnValue(array('mapping' => array('id' => '', 'dependencies' => ''))));
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getPropertiesToExport')
|
||||
->willReturn([]);
|
||||
$properties = $this->entity->toArray();
|
||||
$this->assertInternalType('array', $properties);
|
||||
$this->assertEquals(array('id' => $this->entity->id(), 'dependencies' => array()), $properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::toArray
|
||||
*
|
||||
* @expectedException \Drupal\Core\Config\Schema\SchemaIncompleteException
|
||||
*/
|
||||
public function testToArrayFallback() {
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getPropertiesToExport')
|
||||
->willReturn([]);
|
||||
$this->entity->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getThirdPartySetting
|
||||
* @covers ::setThirdPartySetting
|
||||
* @covers ::getThirdPartySettings
|
||||
* @covers ::unsetThirdPartySetting
|
||||
* @covers ::getThirdPartyProviders
|
||||
*/
|
||||
public function testThirdPartySettings() {
|
||||
$key = 'test';
|
||||
$third_party = 'test_provider';
|
||||
$value = $this->getRandomGenerator()->string();
|
||||
|
||||
// Test getThirdPartySetting() with no settings.
|
||||
$this->assertEquals($value, $this->entity->getThirdPartySetting($third_party, $key, $value));
|
||||
$this->assertNull($this->entity->getThirdPartySetting($third_party, $key));
|
||||
|
||||
// Test setThirdPartySetting().
|
||||
$this->entity->setThirdPartySetting($third_party, $key, $value);
|
||||
$this->assertEquals($value, $this->entity->getThirdPartySetting($third_party, $key));
|
||||
$this->assertEquals($value, $this->entity->getThirdPartySetting($third_party, $key, $this->randomGenerator->string()));
|
||||
|
||||
// Test getThirdPartySettings().
|
||||
$this->entity->setThirdPartySetting($third_party, 'test2', 'value2');
|
||||
$this->assertEquals(array($key => $value, 'test2' => 'value2'), $this->entity->getThirdPartySettings($third_party));
|
||||
|
||||
// Test getThirdPartyProviders().
|
||||
$this->entity->setThirdPartySetting('test_provider2', $key, $value);
|
||||
$this->assertEquals(array($third_party, 'test_provider2'), $this->entity->getThirdPartyProviders());
|
||||
|
||||
// Test unsetThirdPartyProviders().
|
||||
$this->entity->unsetThirdPartySetting('test_provider2', $key);
|
||||
$this->assertEquals(array($third_party), $this->entity->getThirdPartyProviders());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\Entity\ConfigEntityDependencyTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config\Entity;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityDependency;
|
||||
|
||||
/**
|
||||
* Tests the ConfigEntityDependency class.
|
||||
*
|
||||
* @group Config
|
||||
*/
|
||||
class ConfigEntityDependencyTest extends UnitTestCase {
|
||||
|
||||
public function testEmptyDependencies() {
|
||||
$dep = new ConfigEntityDependency('config_test.dynamic.entity_id', array());
|
||||
|
||||
$this->assertEquals('config_test.dynamic.entity_id', $dep->getConfigDependencyName());
|
||||
$this->assertEquals(array(), $dep->getDependencies('theme'));
|
||||
$this->assertEquals(array(), $dep->getDependencies('config'));
|
||||
$this->assertEquals(array('config_test'), $dep->getDependencies('module'));
|
||||
$this->assertTrue($dep->hasDependency('module', 'config_test'));
|
||||
$this->assertFalse($dep->hasDependency('module', 'views'));
|
||||
}
|
||||
|
||||
public function testWithDependencies() {
|
||||
$values = array(
|
||||
'uuid' => '60db47f4-54fb-4c86-a439-5769fbda4bd1',
|
||||
'dependencies' => array(
|
||||
'module' => array(
|
||||
'node',
|
||||
'views'
|
||||
),
|
||||
'config' => array(
|
||||
'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84',
|
||||
),
|
||||
),
|
||||
);
|
||||
$dep = new ConfigEntityDependency('config_test.dynamic.entity_id', $values);
|
||||
|
||||
$this->assertEquals(array(), $dep->getDependencies('theme'));
|
||||
$this->assertEquals(array('config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84'), $dep->getDependencies('config'));
|
||||
$this->assertEquals(array('node', 'views', 'config_test'), $dep->getDependencies('module'));
|
||||
$this->assertTrue($dep->hasDependency('module', 'config_test'));
|
||||
$this->assertTrue($dep->hasDependency('module', 'views'));
|
||||
$this->assertTrue($dep->hasDependency('module', 'node'));
|
||||
$this->assertFalse($dep->hasDependency('module', 'block'));
|
||||
$this->assertTrue($dep->hasDependency('config', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84'));
|
||||
$this->assertFalse($dep->hasDependency('config', 'config_test.dynamic.another_id:7dfa5cb7-2248-4d52-8c00-cd8e02d1e78e'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,882 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\Entity\ConfigEntityStorageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config\Entity {
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Config\Entity\ConfigEntityStorage
|
||||
* @group Config
|
||||
*/
|
||||
class ConfigEntityStorageTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The entity type.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Entity\ConfigEntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entityType;
|
||||
|
||||
/**
|
||||
* The type ID of the entity under test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $entityTypeId;
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The UUID service.
|
||||
*
|
||||
* @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $uuidService;
|
||||
|
||||
/**
|
||||
* The language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The config storage.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Entity\ConfigEntityStorage
|
||||
*/
|
||||
protected $entityStorage;
|
||||
|
||||
/**
|
||||
* The config factory service.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $configFactory;
|
||||
|
||||
/**
|
||||
* The entity query.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\Query\QueryInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entityQuery;
|
||||
|
||||
/**
|
||||
* The entity manager used for testing.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* The mocked cache backend.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $cacheTagsInvalidator;
|
||||
|
||||
/**
|
||||
* The mocked typed config manager.
|
||||
*
|
||||
* @var \Drupal\Core\Config\TypedConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $typedConfigManager;
|
||||
|
||||
/**
|
||||
* The configuration manager.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $configManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @covers ::__construct
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->entityType = $this->getMock('Drupal\Core\Config\Entity\ConfigEntityTypeInterface');
|
||||
$this->entityTypeId = 'test_entity_type';
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getKey')
|
||||
->will($this->returnValueMap(array(
|
||||
array('id', 'id'),
|
||||
array('uuid', 'uuid'),
|
||||
array('langcode', 'langcode'),
|
||||
)));
|
||||
$this->entityType->expects($this->any())
|
||||
->method('id')
|
||||
->will($this->returnValue($this->entityTypeId));
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getConfigPrefix')
|
||||
->will($this->returnValue('the_config_prefix'));
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getClass')
|
||||
->will($this->returnValue(get_class($this->getMockEntity())));
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getListCacheTags')
|
||||
->willReturn(array('test_entity_type_list'));
|
||||
|
||||
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
|
||||
|
||||
$this->uuidService = $this->getMock('Drupal\Component\Uuid\UuidInterface');
|
||||
|
||||
$this->languageManager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
|
||||
$this->languageManager->expects($this->any())
|
||||
->method('getCurrentLanguage')
|
||||
->willReturn(new Language(array('id' => 'hu')));
|
||||
|
||||
$this->configFactory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface');
|
||||
|
||||
$this->entityQuery = $this->getMock('Drupal\Core\Entity\Query\QueryInterface');
|
||||
|
||||
$this->entityStorage = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigEntityStorage')
|
||||
->setConstructorArgs(array($this->entityType, $this->configFactory, $this->uuidService, $this->languageManager))
|
||||
->setMethods(array('getQuery'))
|
||||
->getMock();
|
||||
$this->entityStorage->expects($this->any())
|
||||
->method('getQuery')
|
||||
->will($this->returnValue($this->entityQuery));
|
||||
$this->entityStorage->setModuleHandler($this->moduleHandler);
|
||||
|
||||
$this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
|
||||
$this->entityManager->expects($this->any())
|
||||
->method('getDefinition')
|
||||
->with('test_entity_type')
|
||||
->will($this->returnValue($this->entityType));
|
||||
|
||||
$this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
|
||||
|
||||
$this->typedConfigManager = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface');
|
||||
$this->typedConfigManager->expects($this->any())
|
||||
->method('getDefinition')
|
||||
->will($this->returnValue(array('mapping' => array('id' => '', 'uuid' => '', 'dependencies' => ''))));
|
||||
|
||||
$this->configManager = $this->getMock('Drupal\Core\Config\ConfigManagerInterface');
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('entity.manager', $this->entityManager);
|
||||
$container->set('config.typed', $this->typedConfigManager);
|
||||
$container->set('cache_tags.invalidator', $this->cacheTagsInvalidator);
|
||||
$container->set('config.manager', $this->configManager);
|
||||
$container->set('language_manager', $this->languageManager);
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
* @covers ::doCreate
|
||||
*/
|
||||
public function testCreateWithPredefinedUuid() {
|
||||
$this->cacheTagsInvalidator->expects($this->never())
|
||||
->method('invalidateTags');
|
||||
|
||||
$this->moduleHandler->expects($this->at(0))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_create');
|
||||
$this->moduleHandler->expects($this->at(1))
|
||||
->method('invokeAll')
|
||||
->with('entity_create');
|
||||
$this->uuidService->expects($this->never())
|
||||
->method('generate');
|
||||
|
||||
$entity = $this->entityStorage->create(array('id' => 'foo', 'uuid' => 'baz'));
|
||||
$this->assertInstanceOf('Drupal\Core\Entity\EntityInterface', $entity);
|
||||
$this->assertSame('foo', $entity->id());
|
||||
$this->assertSame('baz', $entity->uuid());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
* @covers ::doCreate
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface
|
||||
*/
|
||||
public function testCreate() {
|
||||
$this->cacheTagsInvalidator->expects($this->never())
|
||||
->method('invalidateTags');
|
||||
|
||||
$this->moduleHandler->expects($this->at(0))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_create');
|
||||
$this->moduleHandler->expects($this->at(1))
|
||||
->method('invokeAll')
|
||||
->with('entity_create');
|
||||
$this->uuidService->expects($this->once())
|
||||
->method('generate')
|
||||
->will($this->returnValue('bar'));
|
||||
|
||||
$entity = $this->entityStorage->create(array('id' => 'foo'));
|
||||
$this->assertInstanceOf('Drupal\Core\Entity\EntityInterface', $entity);
|
||||
$this->assertSame('foo', $entity->id());
|
||||
$this->assertSame('bar', $entity->uuid());
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
* @covers ::doCreate
|
||||
*/
|
||||
public function testCreateWithCurrentLanguage() {
|
||||
$this->languageManager->expects($this->any())
|
||||
->method('getLanguage')
|
||||
->with('hu')
|
||||
->willReturn(new Language(array('id' => 'hu')));
|
||||
|
||||
$entity = $this->entityStorage->create(array('id' => 'foo'));
|
||||
$this->assertSame('hu', $entity->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
* @covers ::doCreate
|
||||
*/
|
||||
public function testCreateWithExplicitLanguage() {
|
||||
$this->languageManager->expects($this->any())
|
||||
->method('getLanguage')
|
||||
->with('en')
|
||||
->willReturn(new Language(array('id' => 'en')));
|
||||
|
||||
$entity = $this->entityStorage->create(array('id' => 'foo', 'langcode' => 'en'));
|
||||
$this->assertSame('en', $entity->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
* @covers ::doSave
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface
|
||||
*
|
||||
* @depends testCreate
|
||||
*/
|
||||
public function testSaveInsert(EntityInterface $entity) {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(TRUE));
|
||||
$config_object->expects($this->exactly(1))
|
||||
->method('setData');
|
||||
$config_object->expects($this->once())
|
||||
->method('save');
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->willReturn([]);
|
||||
|
||||
$this->cacheTagsInvalidator->expects($this->once())
|
||||
->method('invalidateTags')
|
||||
->with(array(
|
||||
$this->entityTypeId . '_list', // List cache tag.
|
||||
));
|
||||
|
||||
$this->configFactory->expects($this->exactly(1))
|
||||
->method('get')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
$this->configFactory->expects($this->exactly(1))
|
||||
->method('getEditable')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
$this->moduleHandler->expects($this->at(0))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_presave');
|
||||
$this->moduleHandler->expects($this->at(1))
|
||||
->method('invokeAll')
|
||||
->with('entity_presave');
|
||||
$this->moduleHandler->expects($this->at(2))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_insert');
|
||||
$this->moduleHandler->expects($this->at(3))
|
||||
->method('invokeAll')
|
||||
->with('entity_insert');
|
||||
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('condition')
|
||||
->with('uuid', 'bar')
|
||||
->will($this->returnSelf());
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$return = $this->entityStorage->save($entity);
|
||||
$this->assertSame(SAVED_NEW, $return);
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
* @covers ::doSave
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface
|
||||
*
|
||||
* @depends testSaveInsert
|
||||
*/
|
||||
public function testSaveUpdate(EntityInterface $entity) {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(FALSE));
|
||||
$config_object->expects($this->exactly(1))
|
||||
->method('setData');
|
||||
$config_object->expects($this->once())
|
||||
->method('save');
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->willReturn([]);
|
||||
|
||||
$this->cacheTagsInvalidator->expects($this->once())
|
||||
->method('invalidateTags')
|
||||
->with(array(
|
||||
// List cache tag only; the own cache tag is invalidated by the config
|
||||
// system.
|
||||
$this->entityTypeId . '_list',
|
||||
));
|
||||
|
||||
$this->configFactory->expects($this->exactly(2))
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo'))
|
||||
->will($this->returnValue(array()));
|
||||
$this->configFactory->expects($this->exactly(1))
|
||||
->method('get')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
$this->configFactory->expects($this->exactly(1))
|
||||
->method('getEditable')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
$this->moduleHandler->expects($this->at(0))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_presave');
|
||||
$this->moduleHandler->expects($this->at(1))
|
||||
->method('invokeAll')
|
||||
->with('entity_presave');
|
||||
$this->moduleHandler->expects($this->at(2))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_update');
|
||||
$this->moduleHandler->expects($this->at(3))
|
||||
->method('invokeAll')
|
||||
->with('entity_update');
|
||||
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('condition')
|
||||
->with('uuid', 'bar')
|
||||
->will($this->returnSelf());
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array($entity->id())));
|
||||
|
||||
$return = $this->entityStorage->save($entity);
|
||||
$this->assertSame(SAVED_UPDATED, $return);
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
* @covers ::doSave
|
||||
*
|
||||
* @depends testSaveInsert
|
||||
*/
|
||||
public function testSaveRename(ConfigEntityInterface $entity) {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(FALSE));
|
||||
$config_object->expects($this->exactly(1))
|
||||
->method('setData');
|
||||
$config_object->expects($this->once())
|
||||
->method('save');
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->willReturn([]);
|
||||
|
||||
$this->cacheTagsInvalidator->expects($this->once())
|
||||
->method('invalidateTags')
|
||||
->with(array(
|
||||
// List cache tag only; the own cache tag is invalidated by the config
|
||||
// system.
|
||||
$this->entityTypeId . '_list',
|
||||
));
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('rename')
|
||||
->willReturn($this->configFactory);
|
||||
$this->configFactory->expects($this->exactly(1))
|
||||
->method('getEditable')
|
||||
->with('the_config_prefix.bar')
|
||||
->will($this->returnValue($config_object));
|
||||
$this->configFactory->expects($this->exactly(2))
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo'))
|
||||
->will($this->returnValue(array()));
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('get')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
// Performing a rename does not change the original ID until saving.
|
||||
$this->assertSame('foo', $entity->getOriginalId());
|
||||
$entity->set('id', 'bar');
|
||||
$this->assertSame('foo', $entity->getOriginalId());
|
||||
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('condition')
|
||||
->with('uuid', 'bar')
|
||||
->will($this->returnSelf());
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array($entity->id())));
|
||||
|
||||
$return = $this->entityStorage->save($entity);
|
||||
$this->assertSame(SAVED_UPDATED, $return);
|
||||
$this->assertSame('bar', $entity->getOriginalId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
*
|
||||
* @expectedException \Drupal\Core\Entity\EntityMalformedException
|
||||
* @expectedExceptionMessage The entity does not have an ID.
|
||||
*/
|
||||
public function testSaveInvalid() {
|
||||
$this->cacheTagsInvalidator->expects($this->never())
|
||||
->method('invalidateTags');
|
||||
|
||||
$entity = $this->getMockEntity();
|
||||
$this->entityStorage->save($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
* @covers ::doSave
|
||||
*
|
||||
* @expectedException \Drupal\Core\Entity\EntityStorageException
|
||||
*/
|
||||
public function testSaveDuplicate() {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(FALSE));
|
||||
$config_object->expects($this->never())
|
||||
->method('set');
|
||||
$config_object->expects($this->never())
|
||||
->method('save');
|
||||
|
||||
$this->cacheTagsInvalidator->expects($this->never())
|
||||
->method('invalidateTags');
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('get')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
$entity = $this->getMockEntity(array('id' => 'foo'));
|
||||
$entity->enforceIsNew();
|
||||
|
||||
$this->entityStorage->save($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
* @covers ::doSave
|
||||
*
|
||||
* @expectedException \Drupal\Core\Config\ConfigDuplicateUUIDException
|
||||
* @expectedExceptionMessage when this UUID is already used for
|
||||
*/
|
||||
public function testSaveMismatch() {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(TRUE));
|
||||
$config_object->expects($this->never())
|
||||
->method('save');
|
||||
|
||||
$this->cacheTagsInvalidator->expects($this->never())
|
||||
->method('invalidateTags');
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('get')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('condition')
|
||||
->will($this->returnSelf());
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array('baz')));
|
||||
|
||||
$entity = $this->getMockEntity(array('id' => 'foo'));
|
||||
$this->entityStorage->save($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
* @covers ::doSave
|
||||
*/
|
||||
public function testSaveNoMismatch() {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(TRUE));
|
||||
$config_object->expects($this->once())
|
||||
->method('save');
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->willReturn([]);
|
||||
|
||||
$this->cacheTagsInvalidator->expects($this->once())
|
||||
->method('invalidateTags')
|
||||
->with(array(
|
||||
$this->entityTypeId . '_list', // List cache tag.
|
||||
));
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('get')
|
||||
->with('the_config_prefix.baz')
|
||||
->will($this->returnValue($config_object));
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('rename')
|
||||
->willReturn($this->configFactory);
|
||||
$this->configFactory->expects($this->exactly(1))
|
||||
->method('getEditable')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('condition')
|
||||
->will($this->returnSelf());
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array('baz')));
|
||||
|
||||
$entity = $this->getMockEntity(array('id' => 'foo'));
|
||||
$entity->setOriginalId('baz');
|
||||
$entity->enforceIsNew();
|
||||
$this->entityStorage->save($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
* @covers ::doSave
|
||||
*
|
||||
* @expectedException \Drupal\Core\Config\ConfigDuplicateUUIDException
|
||||
* @expectedExceptionMessage when this entity already exists with UUID
|
||||
*/
|
||||
public function testSaveChangedUuid() {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(FALSE));
|
||||
$config_object->expects($this->never())
|
||||
->method('save');
|
||||
$config_object->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->will($this->returnValueMap(array(
|
||||
array('', array('id' => 'foo')),
|
||||
array('id', 'foo'),
|
||||
)));
|
||||
|
||||
$this->cacheTagsInvalidator->expects($this->never())
|
||||
->method('invalidateTags');
|
||||
|
||||
$this->configFactory->expects($this->at(1))
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo'))
|
||||
->will($this->returnValue(array()));
|
||||
$this->configFactory->expects($this->at(2))
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo'))
|
||||
->will($this->returnValue(array($config_object)));
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('get')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
$this->configFactory->expects($this->never())
|
||||
->method('rename')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
$this->moduleHandler->expects($this->exactly(2))
|
||||
->method('getImplementations')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('condition')
|
||||
->will($this->returnSelf());
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array('foo')));
|
||||
|
||||
$entity = $this->getMockEntity(array('id' => 'foo'));
|
||||
|
||||
$entity->set('uuid', 'baz');
|
||||
$this->entityStorage->save($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::load
|
||||
* @covers ::postLoad
|
||||
* @covers ::mapFromStorageRecords
|
||||
* @covers ::doLoadMultiple
|
||||
*/
|
||||
public function testLoad() {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->will($this->returnValueMap(array(
|
||||
array('', array('id' => 'foo')),
|
||||
array('id', 'foo'),
|
||||
)));
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo'))
|
||||
->will($this->returnValue(array($config_object)));
|
||||
$this->moduleHandler->expects($this->exactly(2))
|
||||
->method('getImplementations')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$entity = $this->entityStorage->load('foo');
|
||||
$this->assertInstanceOf('Drupal\Core\Entity\EntityInterface', $entity);
|
||||
$this->assertSame('foo', $entity->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::loadMultiple
|
||||
* @covers ::postLoad
|
||||
* @covers ::mapFromStorageRecords
|
||||
* @covers ::doLoadMultiple
|
||||
*/
|
||||
public function testLoadMultipleAll() {
|
||||
$foo_config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$foo_config_object->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->will($this->returnValueMap(array(
|
||||
array('', array('id' => 'foo')),
|
||||
array('id', 'foo'),
|
||||
)));
|
||||
$bar_config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$bar_config_object->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->will($this->returnValueMap(array(
|
||||
array('', array('id' => 'bar')),
|
||||
array('id', 'bar'),
|
||||
)));
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('listAll')
|
||||
->with('the_config_prefix.')
|
||||
->will($this->returnValue(array('the_config_prefix.foo' , 'the_config_prefix.bar')));
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo' , 'the_config_prefix.bar'))
|
||||
->will($this->returnValue(array($foo_config_object, $bar_config_object)));
|
||||
$this->moduleHandler->expects($this->exactly(2))
|
||||
->method('getImplementations')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$entities = $this->entityStorage->loadMultiple();
|
||||
$expected['foo'] = 'foo';
|
||||
$expected['bar'] = 'bar';
|
||||
foreach ($entities as $id => $entity) {
|
||||
$this->assertInstanceOf('Drupal\Core\Entity\EntityInterface', $entity);
|
||||
$this->assertSame($id, $entity->id());
|
||||
$this->assertSame($expected[$id], $entity->id());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::loadMultiple
|
||||
* @covers ::postLoad
|
||||
* @covers ::mapFromStorageRecords
|
||||
* @covers ::doLoadMultiple
|
||||
*/
|
||||
public function testLoadMultipleIds() {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->will($this->returnValueMap(array(
|
||||
array('', array('id' => 'foo')),
|
||||
array('id', 'foo'),
|
||||
)));
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo'))
|
||||
->will($this->returnValue(array($config_object)));
|
||||
$this->moduleHandler->expects($this->exactly(2))
|
||||
->method('getImplementations')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$entities = $this->entityStorage->loadMultiple(array('foo'));
|
||||
foreach ($entities as $id => $entity) {
|
||||
$this->assertInstanceOf('Drupal\Core\Entity\EntityInterface', $entity);
|
||||
$this->assertSame($id, $entity->id());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::loadRevision
|
||||
*/
|
||||
public function testLoadRevision() {
|
||||
$this->assertSame(NULL, $this->entityStorage->loadRevision(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::deleteRevision
|
||||
*/
|
||||
public function testDeleteRevision() {
|
||||
$this->cacheTagsInvalidator->expects($this->never())
|
||||
->method('invalidateTags');
|
||||
|
||||
$this->assertSame(NULL, $this->entityStorage->deleteRevision(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::delete
|
||||
* @covers ::doDelete
|
||||
*/
|
||||
public function testDelete() {
|
||||
// Dependencies are tested in \Drupal\config\Tests\ConfigDependencyTest.
|
||||
$this->configManager->expects($this->any())
|
||||
->method('getConfigEntitiesToChangeOnDependencyRemoval')
|
||||
->willReturn(['update' => [], 'delete' => [], 'unchanged' => []]);
|
||||
$entities = array();
|
||||
$configs = array();
|
||||
$config_map = array();
|
||||
foreach (array('foo', 'bar') as $id) {
|
||||
$entity = $this->getMockEntity(array('id' => $id));
|
||||
$entities[] = $entity;
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->once())
|
||||
->method('delete');
|
||||
$configs[] = $config_object;
|
||||
$config_map[] = array("the_config_prefix.$id", $config_object);
|
||||
}
|
||||
|
||||
$this->cacheTagsInvalidator->expects($this->once())
|
||||
->method('invalidateTags')
|
||||
->with(array(
|
||||
// List cache tag only; the own cache tag is invalidated by the config
|
||||
// system.
|
||||
$this->entityTypeId . '_list',
|
||||
));
|
||||
|
||||
$this->configFactory->expects($this->exactly(2))
|
||||
->method('getEditable')
|
||||
->will($this->returnValueMap($config_map));
|
||||
|
||||
$this->moduleHandler->expects($this->at(0))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_predelete');
|
||||
$this->moduleHandler->expects($this->at(1))
|
||||
->method('invokeAll')
|
||||
->with('entity_predelete');
|
||||
$this->moduleHandler->expects($this->at(2))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_predelete');
|
||||
$this->moduleHandler->expects($this->at(3))
|
||||
->method('invokeAll')
|
||||
->with('entity_predelete');
|
||||
$this->moduleHandler->expects($this->at(4))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_delete');
|
||||
$this->moduleHandler->expects($this->at(5))
|
||||
->method('invokeAll')
|
||||
->with('entity_delete');
|
||||
$this->moduleHandler->expects($this->at(6))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_delete');
|
||||
$this->moduleHandler->expects($this->at(7))
|
||||
->method('invokeAll')
|
||||
->with('entity_delete');
|
||||
|
||||
$this->entityStorage->delete($entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::delete
|
||||
* @covers ::doDelete
|
||||
*/
|
||||
public function testDeleteNothing() {
|
||||
$this->moduleHandler->expects($this->never())
|
||||
->method($this->anything());
|
||||
$this->configFactory->expects($this->never())
|
||||
->method('get');
|
||||
|
||||
$this->cacheTagsInvalidator->expects($this->never())
|
||||
->method('invalidateTags');
|
||||
|
||||
$this->entityStorage->delete(array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an entity with specific methods mocked.
|
||||
*
|
||||
* @param array $values
|
||||
* (optional) Values to pass to the constructor.
|
||||
* @param array $methods
|
||||
* (optional) The methods to mock.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function getMockEntity(array $values = array(), $methods = array()) {
|
||||
return $this->getMockForAbstractClass('Drupal\Core\Config\Entity\ConfigEntityBase', array($values, 'test_entity_type'), '', TRUE, TRUE, TRUE, $methods);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
namespace {
|
||||
if (!defined('SAVED_NEW')) {
|
||||
define('SAVED_NEW', 1);
|
||||
}
|
||||
if (!defined('SAVED_UPDATED')) {
|
||||
define('SAVED_UPDATED', 2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\Entity\ConfigEntityTypeTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config\Entity;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityType;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Config\Entity\ConfigEntityType
|
||||
* @group Config
|
||||
*/
|
||||
class ConfigEntityTypeTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Sets up a ConfigEntityType object for a given set of values.
|
||||
*
|
||||
* @param array $definition
|
||||
* An array of values to use for the ConfigEntityType.
|
||||
*
|
||||
* @return \Drupal\Core\Config\Entity\ConfigEntityTypeInterface
|
||||
*/
|
||||
protected function setUpConfigEntityType($definition) {
|
||||
if (!isset($definition['id'])) {
|
||||
$definition += array(
|
||||
'id' => 'example_config_entity_type',
|
||||
);
|
||||
}
|
||||
return new ConfigEntityType($definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we get an exception when the length of the config prefix that is
|
||||
* returned by getConfigPrefix() exceeds the maximum defined prefix length.
|
||||
*
|
||||
* @covers ::getConfigPrefix
|
||||
*/
|
||||
public function testConfigPrefixLengthExceeds() {
|
||||
$message_text = 'The configuration file name prefix @config_prefix exceeds the maximum character limit of @max_char.';
|
||||
|
||||
// A provider length of 24 and config_prefix length of 59 (+1 for the .)
|
||||
// results in a config length of 84, which is too long.
|
||||
$definition = array(
|
||||
'provider' => $this->randomMachineName(24),
|
||||
'config_prefix' => $this->randomMachineName(59),
|
||||
);
|
||||
$config_entity = $this->setUpConfigEntityType($definition);
|
||||
$this->setExpectedException('\Drupal\Core\Config\ConfigPrefixLengthException', SafeMarkup::format($message_text, array(
|
||||
'@config_prefix' => $definition['provider'] . '.' . $definition['config_prefix'],
|
||||
'@max_char' => ConfigEntityType::PREFIX_LENGTH,
|
||||
)));
|
||||
$this->assertEmpty($config_entity->getConfigPrefix());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a valid config prefix returned by getConfigPrefix()
|
||||
* does not throw an exception and is formatted as expected.
|
||||
*
|
||||
* @covers ::getConfigPrefix
|
||||
*/
|
||||
public function testConfigPrefixLengthValid() {
|
||||
// A provider length of 24 and config_prefix length of 58 (+1 for the .)
|
||||
// results in a config length of 83, which is right at the limit.
|
||||
$definition = array(
|
||||
'provider' => $this->randomMachineName(24),
|
||||
'config_prefix' => $this->randomMachineName(58),
|
||||
);
|
||||
$config_entity = $this->setUpConfigEntityType($definition);
|
||||
$expected_prefix = $definition['provider'] . '.' . $definition['config_prefix'];
|
||||
$this->assertEquals($expected_prefix, $config_entity->getConfigPrefix());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testConstruct() {
|
||||
$config_entity = new ConfigEntityType([
|
||||
'id' => 'example_config_entity_type',
|
||||
]);
|
||||
$this->assertEquals('Drupal\Core\Config\Entity\ConfigEntityStorage', $config_entity->getStorageClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
*
|
||||
* @expectedException \Drupal\Core\Config\Entity\Exception\ConfigEntityStorageClassException
|
||||
* @expectedExceptionMessage \Drupal\Core\Entity\KeyValueStore\KeyValueEntityStorage is not \Drupal\Core\Config\Entity\ConfigEntityStorage or it does not extend it
|
||||
*/
|
||||
public function testConstructBadStorage() {
|
||||
new ConfigEntityType([
|
||||
'id' => 'example_config_entity_type',
|
||||
'handlers' => ['storage' => '\Drupal\Core\Entity\KeyValueStore\KeyValueEntityStorage']
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setStorageClass
|
||||
*
|
||||
* @expectedException \Drupal\Core\Config\Entity\Exception\ConfigEntityStorageClassException
|
||||
* @expectedExceptionMessage \Drupal\Core\Entity\KeyValueStore\KeyValueEntityStorage is not \Drupal\Core\Config\Entity\ConfigEntityStorage or it does not extend it
|
||||
*/
|
||||
public function testSetStorageClass() {
|
||||
$config_entity = $this->setUpConfigEntityType([]);
|
||||
$config_entity->setStorageClass('\Drupal\Core\Entity\KeyValueStore\KeyValueEntityStorage');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getConfigPrefix() method.
|
||||
*
|
||||
* @dataProvider providerTestGetConfigPrefix
|
||||
*
|
||||
* @covers ::getConfigPrefix
|
||||
*/
|
||||
public function testGetConfigPrefix($definition, $expected) {
|
||||
$entity_type = $this->setUpConfigEntityType($definition);
|
||||
$this->assertSame($expected, $entity_type->getConfigPrefix());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data.
|
||||
*/
|
||||
public function providerTestGetConfigPrefix() {
|
||||
return array(
|
||||
array(array('provider' => 'node', 'id' => 'node_type', 'config_prefix' => 'type'), 'node.type'),
|
||||
array(array('provider' => 'views', 'id' => 'view'), 'views.view'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getPropertiesToExport
|
||||
*
|
||||
* @dataProvider providerGetPropertiesToExport
|
||||
*/
|
||||
public function testGetPropertiesToExport($definition, $expected) {
|
||||
$entity_type = $this->setUpConfigEntityType($definition);
|
||||
$properties_to_export = $entity_type->getPropertiesToExport();
|
||||
$this->assertSame($expected, $properties_to_export);
|
||||
|
||||
// Ensure the method is idempotent.
|
||||
$properties_to_export = $entity_type->getPropertiesToExport();
|
||||
$this->assertSame($expected, $properties_to_export);
|
||||
}
|
||||
|
||||
public function providerGetPropertiesToExport() {
|
||||
$data = [];
|
||||
$data[] = [
|
||||
[],
|
||||
NULL,
|
||||
];
|
||||
|
||||
$data[] = [
|
||||
[
|
||||
'config_export' => [
|
||||
'id',
|
||||
'custom_property' => 'customProperty',
|
||||
],
|
||||
],
|
||||
[
|
||||
'uuid' => 'uuid',
|
||||
'langcode' => 'langcode',
|
||||
'status' => 'status',
|
||||
'dependencies' => 'dependencies',
|
||||
'third_party_settings' => 'third_party_settings',
|
||||
'id' => 'id',
|
||||
'custom_property' => 'customProperty',
|
||||
],
|
||||
];
|
||||
|
||||
$data[] = [
|
||||
[
|
||||
'config_export' => [
|
||||
'id',
|
||||
],
|
||||
'mergedConfigExport' => [
|
||||
'random_key' => 'random_key',
|
||||
],
|
||||
],
|
||||
[
|
||||
'random_key' => 'random_key',
|
||||
],
|
||||
];
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\Entity\EntityDisplayBaseTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config\Entity;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Entity\EntityDisplayBase
|
||||
*
|
||||
* @group Config
|
||||
*/
|
||||
class EntityDisplayBaseTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @covers ::getTargetEntityTypeId
|
||||
*/
|
||||
public function testGetTargetEntityTypeId() {
|
||||
$mock = $this->getMockForAbstractClass('\Drupal\Core\Entity\EntityDisplayBase', [], '', FALSE);
|
||||
$reflection = new \ReflectionProperty($mock, 'targetEntityType');
|
||||
$reflection->setAccessible(TRUE);
|
||||
$reflection->setValue($mock, 'test');
|
||||
$this->assertEquals('test', $mock->getTargetEntityTypeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getMode
|
||||
*/
|
||||
public function testGetMode() {
|
||||
$mock = $this->getMockForAbstractClass('\Drupal\Core\Entity\EntityDisplayBase', [], '', FALSE);
|
||||
$reflection = new \ReflectionProperty($mock, 'mode');
|
||||
$reflection->setAccessible(TRUE);
|
||||
$reflection->setValue($mock, 'test');
|
||||
$this->assertEquals('test', $mock->getMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getOriginalMode
|
||||
*/
|
||||
public function testGetOriginalMode() {
|
||||
$mock = $this->getMockForAbstractClass('\Drupal\Core\Entity\EntityDisplayBase', [], '', FALSE);
|
||||
$reflection = new \ReflectionProperty($mock, 'originalMode');
|
||||
$reflection->setAccessible(TRUE);
|
||||
$reflection->setValue($mock, 'test');
|
||||
$this->assertEquals('test', $mock->getOriginalMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getTargetBundle
|
||||
*/
|
||||
public function testGetTargetBundle() {
|
||||
$mock = $this->getMockForAbstractClass('\Drupal\Core\Entity\EntityDisplayBase', [], '', FALSE);
|
||||
$reflection = new \ReflectionProperty($mock, 'bundle');
|
||||
$reflection->setAccessible(TRUE);
|
||||
$reflection->setValue($mock, 'test');
|
||||
$this->assertEquals('test', $mock->getTargetBundle());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setTargetBundle
|
||||
*/
|
||||
public function testSetTargetBundle() {
|
||||
$mock = $this->getMockForAbstractClass('\Drupal\Core\Entity\EntityDisplayBase', [], '', FALSE);
|
||||
$reflection = new \ReflectionProperty($mock, 'bundle');
|
||||
$reflection->setAccessible(TRUE);
|
||||
$mock->setTargetBundle('test');
|
||||
$this->assertEquals('test', $reflection->getValue($mock));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\Entity\EntityDisplayModeBaseUnitTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config\Entity;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Entity\EntityDisplayModeBase
|
||||
* @group Config
|
||||
*/
|
||||
class EntityDisplayModeBaseUnitTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The entity under test.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityDisplayModeBase|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* The entity type used for testing.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entityInfo;
|
||||
|
||||
/**
|
||||
* The entity manager used for testing.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* The ID of the type of the entity under test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $entityType;
|
||||
|
||||
/**
|
||||
* The UUID generator used for testing.
|
||||
*
|
||||
* @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $uuid;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->entityType = $this->randomMachineName();
|
||||
|
||||
$this->entityInfo = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
|
||||
$this->entityInfo->expects($this->any())
|
||||
->method('getProvider')
|
||||
->will($this->returnValue('entity'));
|
||||
|
||||
$this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
|
||||
|
||||
$this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('entity.manager', $this->entityManager);
|
||||
$container->set('uuid', $this->uuid);
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::calculateDependencies
|
||||
*/
|
||||
public function testCalculateDependencies() {
|
||||
$target_entity_type_id = $this->randomMachineName(16);
|
||||
|
||||
$target_entity_type = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
|
||||
$target_entity_type->expects($this->any())
|
||||
->method('getProvider')
|
||||
->will($this->returnValue('test_module'));
|
||||
$values = array('targetEntityType' => $target_entity_type_id);
|
||||
|
||||
$this->entityManager->expects($this->at(0))
|
||||
->method('getDefinition')
|
||||
->with($target_entity_type_id)
|
||||
->will($this->returnValue($target_entity_type));
|
||||
$this->entityManager->expects($this->at(1))
|
||||
->method('getDefinition')
|
||||
->with($this->entityType)
|
||||
->will($this->returnValue($this->entityInfo));
|
||||
|
||||
$this->entity = $this->getMockBuilder('\Drupal\Core\Entity\EntityDisplayModeBase')
|
||||
->setConstructorArgs(array($values, $this->entityType))
|
||||
->setMethods(array('getFilterFormat'))
|
||||
->getMock();
|
||||
|
||||
$dependencies = $this->entity->calculateDependencies();
|
||||
$this->assertContains('test_module', $dependencies['module']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setTargetType
|
||||
*/
|
||||
public function testSetTargetType() {
|
||||
// Generate mock.
|
||||
$mock = $this->getMock(
|
||||
'Drupal\Core\Entity\EntityDisplayModeBase',
|
||||
NULL,
|
||||
array(array('something' => 'nothing'), 'test_type')
|
||||
);
|
||||
|
||||
// Some test values.
|
||||
$bad_target = 'uninitialized';
|
||||
$target = 'test_target_type';
|
||||
|
||||
// Gain access to the protected property.
|
||||
$property = new \ReflectionProperty($mock, 'targetEntityType');
|
||||
$property->setAccessible(TRUE);
|
||||
// Set the property to a known state.
|
||||
$property->setValue($mock, $bad_target);
|
||||
|
||||
// Set the target type.
|
||||
$mock->setTargetType($target);
|
||||
|
||||
// Test the outcome.
|
||||
$this->assertNotEquals($bad_target, $property->getValue($mock));
|
||||
$this->assertEquals($target, $property->getValue($mock));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getTargetType
|
||||
*/
|
||||
public function testGetTargetType() {
|
||||
// Generate mock.
|
||||
$mock = $this->getMock(
|
||||
'Drupal\Core\Entity\EntityDisplayModeBase',
|
||||
NULL,
|
||||
array(array('something' => 'nothing'), 'test_type')
|
||||
);
|
||||
|
||||
// A test value.
|
||||
$target = 'test_target_type';
|
||||
|
||||
// Gain access to the protected property.
|
||||
$property = new \ReflectionProperty($mock, 'targetEntityType');
|
||||
$property->setAccessible(TRUE);
|
||||
// Set the property to a known state.
|
||||
$property->setValue($mock, $target);
|
||||
|
||||
// Get the target type.
|
||||
$value = $mock->getTargetType($target);
|
||||
|
||||
// Test the outcome.
|
||||
$this->assertEquals($value, $property->getValue($mock));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\Entity\Fixtures\ConfigEntityBaseWithPluginCollections.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config\Entity\Fixtures;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBase;
|
||||
use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
|
||||
|
||||
/**
|
||||
* Enables testing of dependency calculation.
|
||||
*
|
||||
* @see \Drupal\Tests\Core\Config\Entity\ConfigEntityBaseUnitTest::testCalculateDependenciesWithPluginCollections()
|
||||
* @see \Drupal\Core\Config\Entity\ConfigEntityBase::calculateDependencies()
|
||||
*/
|
||||
abstract class ConfigEntityBaseWithPluginCollections extends ConfigEntityBase implements EntityWithPluginCollectionInterface {
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\Entity\Query\QueryFactoryTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config\Entity\Query;
|
||||
|
||||
use Drupal\Core\Config\Config;
|
||||
use Drupal\Core\Config\Entity\Query\QueryFactory;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Config\Entity\Query\QueryFactory
|
||||
* @group Config
|
||||
*/
|
||||
class QueryFactoryTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @covers ::getKeys
|
||||
* @covers ::getValues
|
||||
*
|
||||
* @dataProvider providerTestGetKeys
|
||||
*/
|
||||
public function testGetKeys(array $expected, $key, Config $config) {
|
||||
$config_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface');
|
||||
$key_value_factory = $this->getMock('Drupal\Core\KeyValueStore\KeyValueFactoryInterface');
|
||||
$config_manager = $this->getMock('Drupal\Core\Config\ConfigManagerInterface');
|
||||
$config_entity_type = $this->getMock('Drupal\Core\Config\Entity\ConfigEntityTypeInterface');
|
||||
$query_factory = new QueryFactory($config_factory, $key_value_factory, $config_manager);
|
||||
$method = new \ReflectionMethod($query_factory, 'getKeys');
|
||||
$method->setAccessible(TRUE);
|
||||
|
||||
$actual = $method->invoke($query_factory, $config, $key, 'get', $config_entity_type);
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function providerTestGetKeys() {
|
||||
$tests = [];
|
||||
|
||||
$tests[] = [
|
||||
['uuid:abc'],
|
||||
'uuid',
|
||||
$this->getConfigObject('test')->set('uuid', 'abc')
|
||||
];
|
||||
|
||||
// Tests a lookup being set to a top level key when sub-keys exist.
|
||||
$tests[] = [
|
||||
[],
|
||||
'uuid',
|
||||
$this->getConfigObject('test')->set('uuid.blah', 'abc')
|
||||
];
|
||||
|
||||
// Tests a non existent key.
|
||||
$tests[] = [
|
||||
[],
|
||||
'uuid',
|
||||
$this->getConfigObject('test')
|
||||
];
|
||||
|
||||
// Tests a non existent sub key.
|
||||
$tests[] = [
|
||||
[],
|
||||
'uuid.blah',
|
||||
$this->getConfigObject('test')->set('uuid', 'abc')
|
||||
];
|
||||
|
||||
// Tests a existent sub key.
|
||||
$tests[] = [
|
||||
['uuid.blah:abc'],
|
||||
'uuid.blah',
|
||||
$this->getConfigObject('test')->set('uuid.blah', 'abc')
|
||||
];
|
||||
|
||||
// One wildcard.
|
||||
$tests[] = [
|
||||
['test.*.value:a', 'test.*.value:b'],
|
||||
'test.*.value',
|
||||
$this->getConfigObject('test')->set('test.a.value', 'a')->set('test.b.value', 'b')
|
||||
];
|
||||
|
||||
// Three wildcards.
|
||||
$tests[] = [
|
||||
['test.*.sub2.*.sub4.*.value:aaa', 'test.*.sub2.*.sub4.*.value:aab', 'test.*.sub2.*.sub4.*.value:bab'],
|
||||
'test.*.sub2.*.sub4.*.value',
|
||||
$this->getConfigObject('test')
|
||||
->set('test.a.sub2.a.sub4.a.value', 'aaa')
|
||||
->set('test.a.sub2.a.sub4.b.value', 'aab')
|
||||
->set('test.b.sub2.a.sub4.b.value', 'bab')
|
||||
];
|
||||
|
||||
// Three wildcards in a row.
|
||||
$tests[] = [
|
||||
['test.*.*.*.value:abc', 'test.*.*.*.value:abd'],
|
||||
'test.*.*.*.value',
|
||||
$this->getConfigObject('test')->set('test.a.b.c.value', 'abc')->set('test.a.b.d.value', 'abd')
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage test_config_entity_type lookup key test.* ends with a wildcard this can not be used as a lookup
|
||||
*/
|
||||
public function testGetKeysWildCardEnd() {
|
||||
$config_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface');
|
||||
$key_value_factory = $this->getMock('Drupal\Core\KeyValueStore\KeyValueFactoryInterface');
|
||||
$config_manager = $this->getMock('Drupal\Core\Config\ConfigManagerInterface');
|
||||
$config_entity_type = $this->getMock('Drupal\Core\Config\Entity\ConfigEntityTypeInterface');
|
||||
$config_entity_type->expects($this->atLeastOnce())
|
||||
->method('id')
|
||||
->willReturn('test_config_entity_type');
|
||||
$query_factory = new QueryFactory($config_factory, $key_value_factory, $config_manager);
|
||||
|
||||
$method = new \ReflectionMethod($query_factory, 'getKeys');
|
||||
$method->setAccessible(TRUE);
|
||||
$method->invoke($query_factory, $this->getConfigObject('test'), 'test.*', 'get', $config_entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a test configuration object.
|
||||
*
|
||||
* @param string $name
|
||||
* The config name.
|
||||
*
|
||||
* @return \Drupal\Core\Config\Config|\PHPUnit_Framework_MockObject_MockObject
|
||||
* The test configuration object.
|
||||
*/
|
||||
protected function getConfigObject($name) {
|
||||
$config = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['save', 'delete'])
|
||||
->getMock();
|
||||
return $config->setName($name);
|
||||
}
|
||||
}
|
70
core/tests/Drupal/Tests/Core/Config/ImmutableConfigTest.php
Normal file
70
core/tests/Drupal/Tests/Core/Config/ImmutableConfigTest.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\ImmutableConfigTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config;
|
||||
|
||||
use Drupal\Core\Config\ImmutableConfig;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Config\ImmutableConfig
|
||||
* @group Config
|
||||
*/
|
||||
class ImmutableConfigTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The immutable config object under test.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ImmutableConfig
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$storage = $this->getMock('Drupal\Core\Config\StorageInterface');
|
||||
$event_dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
$typed_config = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface');
|
||||
$this->config = new ImmutableConfig('test', $storage, $event_dispatcher, $typed_config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::set
|
||||
* @expectedException \Drupal\Core\Config\ImmutableConfigException
|
||||
* @expectedExceptionMessage Can not set values on immutable configuration test:name. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object
|
||||
*/
|
||||
public function testSet() {
|
||||
$this->config->set('name', 'value');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::clear
|
||||
* @expectedException \Drupal\Core\Config\ImmutableConfigException
|
||||
* @expectedExceptionMessage Can not clear name key in immutable configuration test. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object
|
||||
*/
|
||||
public function testClear() {
|
||||
$this->config->clear('name');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
* @expectedException \Drupal\Core\Config\ImmutableConfigException
|
||||
* @expectedExceptionMessage Can not save immutable configuration test. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object
|
||||
*/
|
||||
public function testSave() {
|
||||
$this->config->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::delete
|
||||
* @expectedException \Drupal\Core\Config\ImmutableConfigException
|
||||
* @expectedExceptionMessage Can not delete immutable configuration test. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object
|
||||
*/
|
||||
public function testDelete() {
|
||||
$this->config->delete();
|
||||
}
|
||||
|
||||
}
|
252
core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php
Normal file
252
core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php
Normal file
|
@ -0,0 +1,252 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\StorageComparerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config;
|
||||
|
||||
use Drupal\Component\Uuid\Php;
|
||||
use Drupal\Core\Config\StorageComparer;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Config\StorageComparer
|
||||
* @group Config
|
||||
*/
|
||||
class StorageComparerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Config\StorageInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $sourceStorage;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Config\StorageInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $targetStorage;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Config\ConfigManager|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $configManager;
|
||||
|
||||
/**
|
||||
* The storage comparer to test.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageComparer
|
||||
*/
|
||||
protected $storageComparer;
|
||||
|
||||
/**
|
||||
* An array of test configuration data keyed by configuration name.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $configData;
|
||||
|
||||
protected function setUp() {
|
||||
$this->sourceStorage = $this->getMock('Drupal\Core\Config\StorageInterface');
|
||||
$this->targetStorage = $this->getMock('Drupal\Core\Config\StorageInterface');
|
||||
$this->configManager = $this->getMock('Drupal\Core\Config\ConfigManagerInterface');
|
||||
$this->storageComparer = new StorageComparer($this->sourceStorage, $this->targetStorage, $this->configManager);
|
||||
}
|
||||
|
||||
protected function getConfigData() {
|
||||
$uuid = new Php();
|
||||
// Mock data using minimal data to use ConfigDependencyManger.
|
||||
$this->configData = array(
|
||||
// Simple config that controls configuration sync.
|
||||
'system.site' => array(
|
||||
'title' => 'Drupal',
|
||||
'uuid' => $uuid->generate(),
|
||||
),
|
||||
// Config entity which requires another config entity.
|
||||
'field.field.node.article.body' => array(
|
||||
'id' => 'node.article.body',
|
||||
'uuid' => $uuid->generate(),
|
||||
'dependencies' => array(
|
||||
'config' => array(
|
||||
'field.storage.node.body'
|
||||
),
|
||||
),
|
||||
),
|
||||
// Config entity which is required by another config entity.
|
||||
'field.storage.node.body' => array(
|
||||
'id' => 'node.body',
|
||||
'uuid' => $uuid->generate(),
|
||||
'dependencies' => array(
|
||||
'module' => array(
|
||||
'text',
|
||||
),
|
||||
),
|
||||
),
|
||||
// Config entity not which has no dependencies on configuration.
|
||||
'views.view.test_view' => array(
|
||||
'id' => 'test_view',
|
||||
'uuid' => $uuid->generate(),
|
||||
'dependencies' => array(
|
||||
'module' => array(
|
||||
'node',
|
||||
),
|
||||
),
|
||||
),
|
||||
// Simple config.
|
||||
'system.performance' => array(
|
||||
'stale_file_threshold' => 2592000
|
||||
),
|
||||
|
||||
);
|
||||
return $this->configData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::createChangelist
|
||||
*/
|
||||
public function testCreateChangelistNoChange() {
|
||||
$config_data = $this->getConfigData();
|
||||
$config_files = array_keys($config_data);
|
||||
$this->sourceStorage->expects($this->once())
|
||||
->method('listAll')
|
||||
->will($this->returnValue($config_files));
|
||||
$this->targetStorage->expects($this->once())
|
||||
->method('listAll')
|
||||
->will($this->returnValue($config_files));
|
||||
$this->sourceStorage->expects($this->once())
|
||||
->method('readMultiple')
|
||||
->will($this->returnValue($config_data));
|
||||
$this->targetStorage->expects($this->once())
|
||||
->method('readMultiple')
|
||||
->will($this->returnValue($config_data));
|
||||
$this->sourceStorage->expects($this->once())
|
||||
->method('getAllCollectionNames')
|
||||
->will($this->returnValue(array()));
|
||||
$this->targetStorage->expects($this->once())
|
||||
->method('getAllCollectionNames')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$this->storageComparer->createChangelist();
|
||||
$this->assertEmpty($this->storageComparer->getChangelist('create'));
|
||||
$this->assertEmpty($this->storageComparer->getChangelist('delete'));
|
||||
$this->assertEmpty($this->storageComparer->getChangelist('update'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::createChangelist
|
||||
*/
|
||||
public function testCreateChangelistCreate() {
|
||||
$target_data = $source_data = $this->getConfigData();
|
||||
unset($target_data['field.storage.node.body']);
|
||||
unset($target_data['field.field.node.article.body']);
|
||||
unset($target_data['views.view.test_view']);
|
||||
|
||||
$this->sourceStorage->expects($this->once())
|
||||
->method('listAll')
|
||||
->will($this->returnValue(array_keys($source_data)));
|
||||
$this->targetStorage->expects($this->once())
|
||||
->method('listAll')
|
||||
->will($this->returnValue(array_keys($target_data)));
|
||||
$this->sourceStorage->expects($this->once())
|
||||
->method('readMultiple')
|
||||
->will($this->returnValue($source_data));
|
||||
$this->targetStorage->expects($this->once())
|
||||
->method('readMultiple')
|
||||
->will($this->returnValue($target_data));
|
||||
$this->sourceStorage->expects($this->once())
|
||||
->method('getAllCollectionNames')
|
||||
->will($this->returnValue(array()));
|
||||
$this->targetStorage->expects($this->once())
|
||||
->method('getAllCollectionNames')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$this->storageComparer->createChangelist();
|
||||
$expected = array(
|
||||
'field.storage.node.body',
|
||||
'views.view.test_view',
|
||||
'field.field.node.article.body',
|
||||
);
|
||||
$this->assertEquals($expected, $this->storageComparer->getChangelist('create'));
|
||||
$this->assertEmpty($this->storageComparer->getChangelist('delete'));
|
||||
$this->assertEmpty($this->storageComparer->getChangelist('update'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::createChangelist
|
||||
*/
|
||||
public function testCreateChangelistDelete() {
|
||||
$target_data = $source_data = $this->getConfigData();
|
||||
unset($source_data['field.storage.node.body']);
|
||||
unset($source_data['field.field.node.article.body']);
|
||||
unset($source_data['views.view.test_view']);
|
||||
|
||||
$this->sourceStorage->expects($this->once())
|
||||
->method('listAll')
|
||||
->will($this->returnValue(array_keys($source_data)));
|
||||
$this->targetStorage->expects($this->once())
|
||||
->method('listAll')
|
||||
->will($this->returnValue(array_keys($target_data)));
|
||||
$this->sourceStorage->expects($this->once())
|
||||
->method('readMultiple')
|
||||
->will($this->returnValue($source_data));
|
||||
$this->targetStorage->expects($this->once())
|
||||
->method('readMultiple')
|
||||
->will($this->returnValue($target_data));
|
||||
$this->sourceStorage->expects($this->once())
|
||||
->method('getAllCollectionNames')
|
||||
->will($this->returnValue(array()));
|
||||
$this->targetStorage->expects($this->once())
|
||||
->method('getAllCollectionNames')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$this->storageComparer->createChangelist();
|
||||
$expected = array(
|
||||
'field.field.node.article.body',
|
||||
'views.view.test_view',
|
||||
'field.storage.node.body',
|
||||
);
|
||||
$this->assertEquals($expected, $this->storageComparer->getChangelist('delete'));
|
||||
$this->assertEmpty($this->storageComparer->getChangelist('create'));
|
||||
$this->assertEmpty($this->storageComparer->getChangelist('update'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::createChangelist
|
||||
*/
|
||||
public function testCreateChangelistUpdate() {
|
||||
$target_data = $source_data = $this->getConfigData();
|
||||
$source_data['system.site']['title'] = 'Drupal New!';
|
||||
$source_data['field.field.node.article.body']['new_config_key'] = 'new data';
|
||||
$source_data['field.storage.node.body']['new_config_key'] = 'new data';
|
||||
|
||||
$this->sourceStorage->expects($this->once())
|
||||
->method('listAll')
|
||||
->will($this->returnValue(array_keys($source_data)));
|
||||
$this->targetStorage->expects($this->once())
|
||||
->method('listAll')
|
||||
->will($this->returnValue(array_keys($target_data)));
|
||||
$this->sourceStorage->expects($this->once())
|
||||
->method('readMultiple')
|
||||
->will($this->returnValue($source_data));
|
||||
$this->targetStorage->expects($this->once())
|
||||
->method('readMultiple')
|
||||
->will($this->returnValue($target_data));
|
||||
$this->sourceStorage->expects($this->once())
|
||||
->method('getAllCollectionNames')
|
||||
->will($this->returnValue(array()));
|
||||
$this->targetStorage->expects($this->once())
|
||||
->method('getAllCollectionNames')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$this->storageComparer->createChangelist();
|
||||
$expected = array(
|
||||
'field.storage.node.body',
|
||||
'system.site',
|
||||
'field.field.node.article.body',
|
||||
);
|
||||
$this->assertEquals($expected, $this->storageComparer->getChangelist('update'));
|
||||
$this->assertEmpty($this->storageComparer->getChangelist('create'));
|
||||
$this->assertEmpty($this->storageComparer->getChangelist('delete'));
|
||||
}
|
||||
|
||||
}
|
79
core/tests/Drupal/Tests/Core/ContentNegotiationTest.php
Normal file
79
core/tests/Drupal/Tests/Core/ContentNegotiationTest.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\ContentNegotiationTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core;
|
||||
|
||||
use Drupal\Core\ContentNegotiation;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\ContentNegotiation
|
||||
* @group ContentNegotiation
|
||||
*/
|
||||
class ContentNegotiationTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\ContentNegotiation
|
||||
*/
|
||||
protected $contentNegotiation;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->contentNegotiation = new ContentNegotiation;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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('ajax', $this->contentNegotiation->getContentType($request));
|
||||
}
|
||||
|
||||
}
|
101
core/tests/Drupal/Tests/Core/Controller/AjaxRendererTest.php
Normal file
101
core/tests/Drupal/Tests/Core/Controller/AjaxRendererTest.php
Normal file
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Controller\AjaxRendererTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Controller;
|
||||
|
||||
use Drupal\Core\Render\MainContent\AjaxRenderer;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Render\MainContent\AjaxRenderer
|
||||
* @group Ajax
|
||||
*/
|
||||
class AjaxRendererTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The tested ajax controller.
|
||||
*
|
||||
* @var \Drupal\Core\Render\MainContent\AjaxRenderer
|
||||
*/
|
||||
protected $ajaxRenderer;
|
||||
|
||||
/**
|
||||
* The renderer.
|
||||
*
|
||||
* @var \Drupal\Core\Render\RendererInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $renderer;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$element_info_manager = $this->getMock('Drupal\Core\Render\ElementInfoManagerInterface');
|
||||
$element_info_manager->expects($this->any())
|
||||
->method('getInfo')
|
||||
->with('ajax')
|
||||
->willReturn([
|
||||
'#header' => TRUE,
|
||||
'#commands' => array(),
|
||||
'#error' => NULL,
|
||||
]);
|
||||
$this->ajaxRenderer = new TestAjaxRenderer($element_info_manager);
|
||||
|
||||
$this->renderer = $this->getMockBuilder('Drupal\Core\Render\Renderer')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(NULL)
|
||||
->getMock();
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('renderer', $this->renderer);
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the content method.
|
||||
*
|
||||
* @covers ::renderResponse
|
||||
*/
|
||||
public function testRenderWithFragmentObject() {
|
||||
$main_content = ['#markup' => 'example content'];
|
||||
$request = new Request();
|
||||
$route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
|
||||
/** @var \Drupal\Core\Ajax\AjaxResponse $result */
|
||||
$result = $this->ajaxRenderer->renderResponse($main_content, $request, $route_match);
|
||||
|
||||
$this->assertInstanceOf('Drupal\Core\Ajax\AjaxResponse', $result);
|
||||
|
||||
$commands = $result->getCommands();
|
||||
$this->assertEquals('insert', $commands[0]['command']);
|
||||
$this->assertEquals('example content', $commands[0]['data']);
|
||||
|
||||
$this->assertEquals('insert', $commands[1]['command']);
|
||||
$this->assertEquals('status_messages', $commands[1]['data']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestAjaxRenderer extends AjaxRenderer {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function drupalRenderRoot(&$elements, $is_root_call = FALSE) {
|
||||
$elements += ['#attached' => []];
|
||||
if (isset($elements['#markup'])) {
|
||||
return $elements['#markup'];
|
||||
}
|
||||
elseif (isset($elements['#type'])) {
|
||||
return $elements['#type'];
|
||||
}
|
||||
else {
|
||||
return 'Markup';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Controller\ControllerBaseTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Controller;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests that the base controller class.
|
||||
*
|
||||
* @group Controller
|
||||
*/
|
||||
class ControllerBaseTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The tested controller base class.
|
||||
*
|
||||
* @var \Drupal\Core\Controller\ControllerBase|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $controllerBase;
|
||||
|
||||
protected function setUp() {
|
||||
$this->controllerBase = $this->getMockForAbstractClass('Drupal\Core\Controller\ControllerBase');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the config method.
|
||||
*/
|
||||
public function testGetConfig() {
|
||||
$config_factory = $this->getConfigFactoryStub(array(
|
||||
'config_name' => array(
|
||||
'key' => 'value',
|
||||
),
|
||||
'config_name2' => array(
|
||||
'key2' => 'value2',
|
||||
),
|
||||
));
|
||||
|
||||
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
|
||||
$container->expects($this->once())
|
||||
->method('get')
|
||||
->with('config.factory')
|
||||
->will($this->returnValue($config_factory));
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$config_method = new \ReflectionMethod('Drupal\Core\Controller\ControllerBase', 'config');
|
||||
$config_method->setAccessible(TRUE);
|
||||
|
||||
// Call config twice to ensure that the container is just called once.
|
||||
$config = $config_method->invoke($this->controllerBase, 'config_name');
|
||||
$this->assertEquals('value', $config->get('key'));
|
||||
|
||||
$config = $config_method->invoke($this->controllerBase, 'config_name2');
|
||||
$this->assertEquals('value2', $config->get('key2'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Controller\ControllerResolverTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerResolver;
|
||||
use Drupal\Core\DependencyInjection\ClassResolver;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Routing\RouteMatch;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\DependencyInjection\ContainerAware;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Controller\ControllerResolver
|
||||
* @group Controller
|
||||
*/
|
||||
class ControllerResolverTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The tested controller resolver.
|
||||
*
|
||||
* @var \Drupal\Core\Controller\ControllerResolver
|
||||
*/
|
||||
public $controllerResolver;
|
||||
|
||||
/**
|
||||
* The container.
|
||||
*
|
||||
* @var \Symfony\Component\DependencyInjection\ContainerBuilder
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->container = new ContainerBuilder();
|
||||
$class_resolver = new ClassResolver();
|
||||
$class_resolver->setContainer($this->container);
|
||||
$this->controllerResolver = new ControllerResolver($class_resolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests getArguments().
|
||||
*
|
||||
* Ensure that doGetArguments uses converted arguments if available.
|
||||
*
|
||||
* @see \Drupal\Core\Controller\ControllerResolver::getArguments()
|
||||
* @see \Drupal\Core\Controller\ControllerResolver::doGetArguments()
|
||||
*/
|
||||
public function testGetArguments() {
|
||||
$controller = function(EntityInterface $entity, $user, RouteMatchInterface $route_match) {
|
||||
};
|
||||
$mock_entity = $this->getMockBuilder('Drupal\Core\Entity\Entity')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$mock_account = $this->getMock('Drupal\Core\Session\AccountInterface');
|
||||
$request = new Request(array(), array(), array(
|
||||
'entity' => $mock_entity,
|
||||
'user' => $mock_account,
|
||||
'_raw_variables' => new ParameterBag(array('entity' => 1, 'user' => 1)),
|
||||
));
|
||||
$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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests createController().
|
||||
*
|
||||
* @dataProvider providerTestCreateController
|
||||
*/
|
||||
public function testCreateController($controller, $class, $output) {
|
||||
$this->container->set('some_service', new MockController());
|
||||
$result = $this->controllerResolver->getControllerFromDefinition($controller);
|
||||
$this->assertCallableController($result, $class, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testCreateController().
|
||||
*/
|
||||
public function providerTestCreateController() {
|
||||
return array(
|
||||
// Tests class::method.
|
||||
array('Drupal\Tests\Core\Controller\MockController::getResult', 'Drupal\Tests\Core\Controller\MockController', 'This is a regular controller.'),
|
||||
// Tests service:method.
|
||||
array('some_service:getResult', 'Drupal\Tests\Core\Controller\MockController', 'This is a regular controller.'),
|
||||
// Tests a class with injection.
|
||||
array('Drupal\Tests\Core\Controller\MockContainerInjection::getResult', 'Drupal\Tests\Core\Controller\MockContainerInjection', 'This used injection.'),
|
||||
// Tests a ContainerAware class.
|
||||
array('Drupal\Tests\Core\Controller\MockContainerAware::getResult', 'Drupal\Tests\Core\Controller\MockContainerAware', 'This is container aware.'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests createController() with a non-existent class.
|
||||
*
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testCreateControllerNonExistentClass() {
|
||||
$this->controllerResolver->getControllerFromDefinition('Class::method');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests createController() with an invalid name.
|
||||
*
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testCreateControllerInvalidName() {
|
||||
$this->controllerResolver->getControllerFromDefinition('ClassWithoutMethod');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests getController().
|
||||
*
|
||||
* @dataProvider providerTestGetController
|
||||
*/
|
||||
public function testGetController($attributes, $class, $output = NULL) {
|
||||
$request = new Request(array(), array(), $attributes);
|
||||
$result = $this->controllerResolver->getController($request);
|
||||
if ($class) {
|
||||
$this->assertCallableController($result, $class, $output);
|
||||
}
|
||||
else {
|
||||
$this->assertSame(FALSE, $result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testGetController().
|
||||
*/
|
||||
public function providerTestGetController() {
|
||||
return array(
|
||||
// Tests passing a controller via the request.
|
||||
array(array('_controller' => 'Drupal\Tests\Core\Controller\MockContainerAware::getResult'), 'Drupal\Tests\Core\Controller\MockContainerAware', 'This is container aware.'),
|
||||
// Tests a request with no controller specified.
|
||||
array(array(), FALSE)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests getControllerFromDefinition().
|
||||
*
|
||||
* @dataProvider providerTestGetControllerFromDefinition
|
||||
*/
|
||||
public function testGetControllerFromDefinition($definition, $output) {
|
||||
$controller = $this->controllerResolver->getControllerFromDefinition($definition);
|
||||
$this->assertCallableController($controller, NULL, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testGetControllerFromDefinition().
|
||||
*/
|
||||
public function providerTestGetControllerFromDefinition() {
|
||||
return array(
|
||||
// Tests a method on an object.
|
||||
array(array(new MockController(), 'getResult'), 'This is a regular controller.'),
|
||||
// Tests a function.
|
||||
array('phpversion', phpversion()),
|
||||
// Tests an object using __invoke().
|
||||
array(new MockInvokeController(), 'This used __invoke().'),
|
||||
// Tests a class using __invoke().
|
||||
array('Drupal\Tests\Core\Controller\MockInvokeController', 'This used __invoke().'),
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Tests getControllerFromDefinition() without a callable.
|
||||
*
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testGetControllerFromDefinitionNotCallable() {
|
||||
$this->controllerResolver->getControllerFromDefinition('Drupal\Tests\Core\Controller\MockController::bananas');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the controller is callable and produces the correct output.
|
||||
*
|
||||
* @param callable $controller
|
||||
* A callable controller.
|
||||
* @param string|null $class
|
||||
* Either the name of the class the controller represents, or NULL if it is
|
||||
* not an object.
|
||||
* @param mixed $output
|
||||
* The output expected for this controller.
|
||||
*/
|
||||
protected function assertCallableController($controller, $class, $output) {
|
||||
if ($class) {
|
||||
$this->assertTrue(is_object($controller[0]));
|
||||
$this->assertInstanceOf($class, $controller[0]);
|
||||
}
|
||||
$this->assertTrue(is_callable($controller));
|
||||
$this->assertSame($output, call_user_func($controller));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests getArguments with a route match and a request.
|
||||
*
|
||||
* @covers ::getArguments
|
||||
* @covers ::doGetArguments
|
||||
*/
|
||||
public function testGetArgumentsWithRouteMatchAndRequest() {
|
||||
$request = Request::create('/test');
|
||||
$mock_controller = new MockController();
|
||||
$arguments = $this->controllerResolver->getArguments($request, [$mock_controller, 'getControllerWithRequestAndRouteMatch']);
|
||||
$this->assertEquals([RouteMatch::createFromRequest($request), $request], $arguments);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MockController {
|
||||
public function getResult() {
|
||||
return 'This is a regular controller.';
|
||||
}
|
||||
|
||||
public function getControllerWithRequestAndRouteMatch(RouteMatchInterface $route_match, Request $request) {
|
||||
return 'this is another example controller';
|
||||
}
|
||||
|
||||
}
|
||||
class MockContainerInjection implements ContainerInjectionInterface {
|
||||
protected $result;
|
||||
public function __construct($result) {
|
||||
$this->result = $result;
|
||||
}
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static('This used injection.');
|
||||
}
|
||||
public function getResult() {
|
||||
return $this->result;
|
||||
}
|
||||
}
|
||||
class MockContainerAware extends ContainerAware {
|
||||
public function getResult() {
|
||||
return 'This is container aware.';
|
||||
}
|
||||
}
|
||||
class MockInvokeController {
|
||||
public function __invoke() {
|
||||
return 'This used __invoke().';
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue