Update to Drupal 8.2.0. For more information, see https://www.drupal.org/project/drupal/releases/8.2.0

This commit is contained in:
Pantheon Automation 2016-10-06 15:16:20 -07:00 committed by Greg Anderson
parent 2f563ab520
commit f1c8716f57
1732 changed files with 52334 additions and 11780 deletions

View file

@ -0,0 +1,69 @@
<?php
/**
* @file
* Contains database additions to drupal-8.bare.standard.php.gz for testing the
* upgrade path of rest_update_8201().
*/
use Drupal\Core\Database\Database;
$connection = Database::getConnection();
// Set the schema version.
$connection->insert('key_value')
->fields([
'collection' => 'system.schema',
'name' => 'rest',
'value' => 'i:8000;',
])
->fields([
'collection' => 'system.schema',
'name' => 'serialization',
'value' => 'i:8000;',
])
->fields([
'collection' => 'system.schema',
'name' => 'basic_auth',
'value' => 'i:8000;',
])
->execute();
// Update core.extension.
$extensions = $connection->select('config')
->fields('config', ['data'])
->condition('collection', '')
->condition('name', 'core.extension')
->execute()
->fetchField();
$extensions = unserialize($extensions);
$extensions['module']['basic_auth'] = 8000;
$extensions['module']['rest'] = 8000;
$extensions['module']['serialization'] = 8000;
$connection->update('config')
->fields([
'data' => serialize($extensions),
])
->condition('collection', '')
->condition('name', 'core.extension')
->execute();
// Install the rest configuration.
$config = [
'resources' => [
'entity:node' => [
'GET' => [
'supported_formats' => ['json'],
'supported_auth' => ['basic_auth'],
],
],
],
'link_domain' => '~',
];
$data = $connection->insert('config')
->fields([
'name' => 'rest.settings',
'data' => serialize($config),
'collection' => ''
])
->execute();

View file

@ -0,0 +1,63 @@
<?php
/**
* @file
* Contains database additions to drupal-8.bare.standard.php.gz for testing the
* upgrade path of rest_update_8203().
*/
use Drupal\Core\Database\Database;
$connection = Database::getConnection();
// Set the schema version.
$connection->insert('key_value')
->fields([
'collection' => 'system.schema',
'name' => 'rest',
'value' => 'i:8000;',
])
->fields([
'collection' => 'system.schema',
'name' => 'serialization',
'value' => 'i:8000;',
])
->execute();
// Update core.extension.
$extensions = $connection->select('config')
->fields('config', ['data'])
->condition('collection', '')
->condition('name', 'core.extension')
->execute()
->fetchField();
$extensions = unserialize($extensions);
$extensions['module']['rest'] = 8000;
$extensions['module']['serialization'] = 8000;
$connection->update('config')
->fields([
'data' => serialize($extensions),
])
->condition('collection', '')
->condition('name', 'core.extension')
->execute();
// Install the rest configuration.
$config = [
'resources' => [
'entity:node' => [
'GET' => [
'supported_formats' => ['json'],
'supported_auth' => ['basic_auth'],
],
],
],
'link_domain' => '~',
];
$data = $connection->insert('config')
->fields([
'name' => 'rest.settings',
'data' => serialize($config),
'collection' => ''
])
->execute();

View file

@ -0,0 +1,75 @@
<?php
/**
* @file
* Test fixture for \Drupal\rest\Tests\Update\RestExportAuthUpdateTest.
*/
use Drupal\Core\Database\Database;
use Drupal\Core\Serialization\Yaml;
$connection = Database::getConnection();
$config = $connection;
// Set the schema version.
$connection->insert('key_value')
->fields([
'collection' => 'system.schema',
'name' => 'rest',
'value' => 'i:8000;',
])
->fields([
'collection' => 'system.schema',
'name' => 'serialization',
'value' => 'i:8000;',
])
->fields([
'collection' => 'system.schema',
'name' => 'basic_auth',
'value' => 'i:8000;',
])
->execute();
// Update core.extension.
$extensions = $connection->select('config')
->fields('config', ['data'])
->condition('collection', '')
->condition('name', 'core.extension')
->execute()
->fetchField();
$extensions = unserialize($extensions);
$extensions['module']['rest'] = 0;
$extensions['module']['serialization'] = 0;
$extensions['module']['basic_auth'] = 0;
$connection->update('config')
->fields([
'data' => serialize($extensions),
])
->condition('collection', '')
->condition('name', 'core.extension')
->execute();
$config = [
'link_domain' => '~',
];
$data = $connection->insert('config')
->fields([
'name' => 'rest.settings',
'data' => serialize($config),
'collection' => '',
])
->execute();
$connection->insert('config')
->fields([
'name' => 'views.view.rest_export_with_authorization',
])
->execute();
$connection->merge('config')
->condition('name', 'views.view.rest_export_with_authorization')
->condition('collection', '')
->fields([
'data' => serialize(Yaml::decode(file_get_contents('core/modules/views/tests/modules/views_test_config/test_views/views.view.rest_export_with_authorization.yml'))),
])
->execute();

View file

@ -0,0 +1,32 @@
id: entity.comment
plugin_id: 'entity:comment'
granularity: method
configuration:
GET:
supported_formats:
- hal_json
# This resource has a method-specific format.
# @see \Drupal\rest\Tests\Update\ResourceGranularityUpdateTest
- xml
supported_auth:
- basic_auth
POST:
supported_formats:
- hal_json
supported_auth:
- basic_auth
PATCH:
supported_formats:
- hal_json
supported_auth:
- basic_auth
DELETE:
supported_formats:
- hal_json
supported_auth:
- basic_auth
dependencies:
module:
- node
- basic_auth
- hal

View file

@ -0,0 +1,29 @@
id: entity.node
plugin_id: 'entity:node'
granularity: method
configuration:
GET:
supported_formats:
- hal_json
supported_auth:
- basic_auth
POST:
supported_formats:
- hal_json
supported_auth:
- basic_auth
PATCH:
supported_formats:
- hal_json
supported_auth:
- basic_auth
DELETE:
supported_formats:
- hal_json
supported_auth:
- basic_auth
dependencies:
module:
- node
- basic_auth
- hal

View file

@ -0,0 +1,32 @@
id: entity.user
plugin_id: 'entity:user'
granularity: method
configuration:
GET:
supported_formats:
- hal_json
supported_auth:
- basic_auth
# This resource has a method-specific authentication.
# @see \Drupal\rest\Tests\Update\ResourceGranularityUpdateTest
- oauth
POST:
supported_formats:
- hal_json
supported_auth:
- basic_auth
PATCH:
supported_formats:
- hal_json
supported_auth:
- basic_auth
DELETE:
supported_formats:
- hal_json
supported_auth:
- basic_auth
dependencies:
module:
- node
- basic_auth
- hal

View file

@ -1,6 +1,6 @@
name: 'REST test'
type: module
description: 'Provides test hooks for REST module.'
description: 'Provides test hooks and resources for REST module.'
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,32 @@
<?php
namespace Drupal\rest_test\Plugin\rest\resource;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
/**
* Class used to test that serialization_class is optional.
*
* @RestResource(
* id = "serialization_test",
* label = @Translation("Optional serialization_class"),
* serialization_class = "",
* uri_paths = {}
* )
*/
class NoSerializationClassTestResource extends ResourceBase {
/**
* Responds to a POST request.
*
* @param array $data
* An array with the payload.
*
* @return \Drupal\rest\ResourceResponse
*/
public function post(array $data = []) {
return new ResourceResponse($data);
}
}

View file

@ -0,0 +1,21 @@
<?php
/**
* @file
* Test hook implementations for the REST views test module.
*/
use Drupal\views\ViewExecutable;
/**
* Implements hook_views_post_execute().
*/
function rest_test_views_views_post_execute(ViewExecutable $view) {
// Attach a custom header to the test_data_export view.
if ($view->id() === 'test_serializer_display_entity') {
if ($value = \Drupal::state()->get('rest_test_views_set_header', FALSE)) {
$view->getResponse()->headers->set('Custom-Header', $value);
}
}
}

View file

@ -27,7 +27,7 @@ display:
access:
type: perm
options:
perm: 'access content'
perm: 'administer views'
cache:
type: tag
query:
@ -149,3 +149,24 @@ display:
type: serializer
row:
type: data_field
rest_export_2:
display_plugin: rest_export
id: rest_export_2
display_title: 'REST export 2'
position: 2
display_options:
display_extenders: { }
auth:
basic_auth: basic_auth
path: test/serialize/auth_with_perm
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- request_format
- 'user.node_grants:view'
- user.permissions
tags:
- 'config:field.storage.node.body'

View file

@ -0,0 +1,289 @@
<?php
namespace Drupal\Tests\rest\Kernel\Entity;
use Drupal\KernelTests\KernelTestBase;
use Drupal\rest\Entity\ConfigDependencies;
use Drupal\rest\Entity\RestResourceConfig;
use Drupal\rest\RestResourceConfigInterface;
/**
* @coversDefaultClass \Drupal\rest\Entity\ConfigDependencies
*
* @group rest
*/
class ConfigDependenciesTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['rest', 'entity_test', 'serialization'];
/**
* @covers ::calculateDependencies
*
* @dataProvider providerBasicDependencies
*/
public function testCalculateDependencies(array $configuration) {
$config_dependencies = new ConfigDependencies(['hal_json' => 'hal', 'json' => 'serialization'], ['basic_auth' => 'basic_auth']);
$rest_config = RestResourceConfig::create($configuration);
$result = $config_dependencies->calculateDependencies($rest_config);
$this->assertEquals(['module' => [
'basic_auth', 'serialization', 'hal',
]], $result);
}
/**
* @covers ::onDependencyRemoval
* @covers ::onDependencyRemovalForMethodGranularity
* @covers ::onDependencyRemovalForResourceGranularity
*
* @dataProvider providerBasicDependencies
*/
public function testOnDependencyRemovalRemoveUnrelatedDependency(array $configuration) {
$config_dependencies = new ConfigDependencies(['hal_json' => 'hal', 'json' => 'serialization'], ['basic_auth' => 'basic_auth']);
$rest_config = RestResourceConfig::create($configuration);
$this->assertFalse($config_dependencies->onDependencyRemoval($rest_config, ['module' => ['node']]));
$this->assertEquals($configuration['configuration'], $rest_config->get('configuration'));
}
/**
* @return array
* An array with numerical keys:
* 0. The original REST resource configuration.
*/
public function providerBasicDependencies() {
return [
'method' => [
[
'plugin_id' => 'entity:entity_test',
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
'configuration' => [
'GET' => [
'supported_auth' => ['basic_auth'],
'supported_formats' => ['json'],
],
'POST' => [
'supported_auth' => ['cookie'],
'supported_formats' => ['hal_json'],
],
],
],
],
'resource' => [
[
'plugin_id' => 'entity:entity_test',
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
'configuration' => [
'methods' => ['GET', 'POST'],
'formats' => ['json', 'hal_json'],
'authentication' => ['cookie', 'basic_auth'],
],
],
],
];
}
/**
* @covers ::onDependencyRemoval
* @covers ::onDependencyRemovalForMethodGranularity
*/
public function testOnDependencyRemovalRemoveFormatForMethodGranularity() {
$config_dependencies = new ConfigDependencies(['hal_json' => 'hal', 'json' => 'serialization'], ['basic_auth' => 'basic_auth']);
$rest_config = RestResourceConfig::create([
'plugin_id' => 'entity:entity_test',
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
'configuration' => [
'GET' => [
'supported_auth' => ['cookie'],
'supported_formats' => ['json'],
],
'POST' => [
'supported_auth' => ['basic_auth'],
'supported_formats' => ['hal_json'],
],
],
]);
$this->assertTrue($config_dependencies->onDependencyRemoval($rest_config, ['module' => ['hal']]));
$this->assertEquals(['json'], $rest_config->getFormats('GET'));
$this->assertEquals([], $rest_config->getFormats('POST'));
$this->assertEquals([
'GET' => [
'supported_auth' => ['cookie'],
'supported_formats' => ['json'],
],
'POST' => [
'supported_auth' => ['basic_auth'],
],
], $rest_config->get('configuration'));
}
/**
* @covers ::onDependencyRemoval
* @covers ::onDependencyRemovalForMethodGranularity
*/
public function testOnDependencyRemovalRemoveAuth() {
$config_dependencies = new ConfigDependencies(['hal_json' => 'hal', 'json' => 'serialization'], ['basic_auth' => 'basic_auth']);
$rest_config = RestResourceConfig::create([
'plugin_id' => 'entity:entity_test',
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
'configuration' => [
'GET' => [
'supported_auth' => ['cookie'],
'supported_formats' => ['json'],
],
'POST' => [
'supported_auth' => ['basic_auth'],
'supported_formats' => ['hal_json'],
],
],
]);
$this->assertTrue($config_dependencies->onDependencyRemoval($rest_config, ['module' => ['basic_auth']]));
$this->assertEquals(['cookie'], $rest_config->getAuthenticationProviders('GET'));
$this->assertEquals([], $rest_config->getAuthenticationProviders('POST'));
$this->assertEquals([
'GET' => [
'supported_auth' => ['cookie'],
'supported_formats' => ['json'],
],
'POST' => [
'supported_formats' => ['hal_json'],
],
], $rest_config->get('configuration'));
}
/**
* @covers ::onDependencyRemoval
* @covers ::onDependencyRemovalForMethodGranularity
*/
public function testOnDependencyRemovalRemoveAuthAndFormats() {
$config_dependencies = new ConfigDependencies(['hal_json' => 'hal', 'json' => 'serialization'], ['basic_auth' => 'basic_auth']);
$rest_config = RestResourceConfig::create([
'plugin_id' => 'entity:entity_test',
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
'configuration' => [
'GET' => [
'supported_auth' => ['cookie'],
'supported_formats' => ['json'],
],
'POST' => [
'supported_auth' => ['basic_auth'],
'supported_formats' => ['hal_json'],
],
],
]);
$this->assertTrue($config_dependencies->onDependencyRemoval($rest_config, ['module' => ['basic_auth', 'hal']]));
$this->assertEquals(['json'], $rest_config->getFormats('GET'));
$this->assertEquals(['cookie'], $rest_config->getAuthenticationProviders('GET'));
$this->assertEquals([], $rest_config->getFormats('POST'));
$this->assertEquals([], $rest_config->getAuthenticationProviders('POST'));
$this->assertEquals([
'GET' => [
'supported_auth' => ['cookie'],
'supported_formats' => ['json'],
],
], $rest_config->get('configuration'));
}
/**
* @covers ::onDependencyRemoval
* @covers ::onDependencyRemovalForResourceGranularity
*
* @dataProvider providerOnDependencyRemovalForResourceGranularity
*/
public function testOnDependencyRemovalForResourceGranularity(array $configuration, $module, $expected_configuration) {
assert('is_string($module)');
assert('$expected_configuration === FALSE || is_array($expected_configuration)');
$config_dependencies = new ConfigDependencies(['hal_json' => 'hal', 'json' => 'serialization'], ['basic_auth' => 'basic_auth']);
$rest_config = RestResourceConfig::create($configuration);
$this->assertSame(!empty($expected_configuration), $config_dependencies->onDependencyRemoval($rest_config, ['module' => [$module]]));
if (!empty($expected_configuration)) {
$this->assertEquals($expected_configuration, $rest_config->get('configuration'));
}
}
/**
* @return array
* An array with numerical keys:
* 0. The original REST resource configuration.
* 1. The module to uninstall (the dependency that is about to be removed).
* 2. The expected configuration after uninstalling this module.
*/
public function providerOnDependencyRemovalForResourceGranularity() {
return [
'resource with multiple formats' => [
[
'plugin_id' => 'entity:entity_test',
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
'configuration' => [
'methods' => ['GET', 'POST'],
'formats' => ['json', 'hal_json'],
'authentication' => ['cookie', 'basic_auth'],
],
],
'hal',
[
'methods' => ['GET', 'POST'],
'formats' => ['json'],
'authentication' => ['cookie', 'basic_auth'],
]
],
'resource with only HAL+JSON format' => [
[
'plugin_id' => 'entity:entity_test',
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
'configuration' => [
'methods' => ['GET', 'POST'],
'formats' => ['hal_json'],
'authentication' => ['cookie', 'basic_auth'],
],
],
'hal',
FALSE
],
'resource with multiple authentication providers' => [
[
'plugin_id' => 'entity:entity_test',
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
'configuration' => [
'methods' => ['GET', 'POST'],
'formats' => ['json', 'hal_json'],
'authentication' => ['cookie', 'basic_auth'],
],
],
'basic_auth',
[
'methods' => ['GET', 'POST'],
'formats' => ['json', 'hal_json'],
'authentication' => ['cookie'],
]
],
'resource with only basic_auth authentication' => [
[
'plugin_id' => 'entity:entity_test',
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
'configuration' => [
'methods' => ['GET', 'POST'],
'formats' => ['json', 'hal_json'],
'authentication' => ['basic_auth'],
],
],
'basic_auth',
FALSE,
],
];
}
}

View file

@ -0,0 +1,44 @@
<?php
namespace Drupal\Tests\rest\Kernel\Entity;
use Drupal\KernelTests\KernelTestBase;
use Drupal\rest\Entity\RestResourceConfig;
use Drupal\rest\RestResourceConfigInterface;
/**
* @coversDefaultClass \Drupal\rest\Entity\RestResourceConfig
*
* @group rest
*/
class RestResourceConfigTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['rest', 'entity_test', 'serialization', 'basic_auth', 'user', 'hal'];
/**
* @covers ::calculateDependencies
*/
public function testCalculateDependencies() {
$rest_config = RestResourceConfig::create([
'plugin_id' => 'entity:entity_test',
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
'configuration' => [
'GET' => [
'supported_auth' => ['cookie'],
'supported_formats' => ['json'],
],
'POST' => [
'supported_auth' => ['basic_auth'],
'supported_formats' => ['hal_json'],
],
],
]);
$rest_config->calculateDependencies();
$this->assertEquals(['module' => ['basic_auth', 'entity_test', 'hal', 'serialization', 'user']], $rest_config->getDependencies());
}
}

View file

@ -1,18 +1,17 @@
<?php
/**
* @file
* Contains \Drupal\Tests\rest\Kernel\RequestHandlerTest.
*/
namespace Drupal\Tests\rest\Kernel;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Routing\RouteMatch;
use Drupal\KernelTests\KernelTestBase;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\Plugin\Type\ResourcePluginManager;
use Drupal\rest\RequestHandler;
use Drupal\rest\ResourceResponse;
use Drupal\rest\RestResourceConfigInterface;
use Prophecy\Argument;
use Prophecy\Prophecy\MethodProphecy;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;
@ -31,12 +30,20 @@ class RequestHandlerTest extends KernelTestBase {
public static $modules = ['serialization', 'rest'];
/**
* The entity storage.
*
* @var \Prophecy\Prophecy\ObjectProphecy
*/
protected $entityStorage;
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
$this->requestHandler = new RequestHandler();
$this->entityStorage = $this->prophesize(EntityStorageInterface::class);
$this->requestHandler = new RequestHandler($this->entityStorage->reveal());
$this->requestHandler->setContainer($this->container);
}
@ -47,17 +54,19 @@ class RequestHandlerTest extends KernelTestBase {
*/
public function testBaseHandler() {
$request = new Request();
$route_match = new RouteMatch('test', new Route('/rest/test', ['_plugin' => 'restplugin', '_format' => 'json']));
$route_match = new RouteMatch('test', new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_format' => 'json']));
$resource = $this->prophesize(StubRequestHandlerResourcePlugin::class);
$resource->get(NULL, $request)
->shouldBeCalled();
// Setup stub plugin manager that will return our plugin.
$stub = $this->prophesize(ResourcePluginManager::class);
$stub->getInstance(['id' => 'restplugin'])
->willReturn($resource->reveal());
$this->container->set('plugin.manager.rest', $stub->reveal());
// Setup the configuration.
$config = $this->prophesize(RestResourceConfigInterface::class);
$config->getResourcePlugin()->willReturn($resource->reveal());
$config->getCacheContexts()->willReturn([]);
$config->getCacheTags()->willReturn([]);
$config->getCacheMaxAge()->willReturn(12);
$this->entityStorage->load('restplugin')->willReturn($config->reveal());
// Response returns NULL this time because response from plugin is not
// a ResourceResponse so it is passed through directly.
@ -72,6 +81,7 @@ class RequestHandlerTest extends KernelTestBase {
$this->assertEquals($response, $handler_response);
// We will call the patch method this time.
$route_match = new RouteMatch('test', new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_content_type_format' => 'json']));
$request->setMethod('PATCH');
$response = new ResourceResponse([]);
$resource->patch(NULL, $request)
@ -87,29 +97,32 @@ class RequestHandlerTest extends KernelTestBase {
* @dataProvider providerTestSerialization
* @covers ::handle
*/
public function testSerialization($data) {
public function testSerialization($data, $expected_response = FALSE) {
$request = new Request();
$route_match = new RouteMatch('test', new Route('/rest/test', ['_plugin' => 'restplugin', '_format' => 'json']));
$route_match = new RouteMatch('test', new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_format' => 'json']));
$resource = $this->prophesize(StubRequestHandlerResourcePlugin::class);
// Setup stub plugin manager that will return our plugin.
$stub = $this->prophesize(ResourcePluginManager::class);
$stub->getInstance(['id' => 'restplugin'])
->willReturn($resource->reveal());
$this->container->set('plugin.manager.rest', $stub->reveal());
// Mock the configuration.
$config = $this->prophesize(RestResourceConfigInterface::class);
$config->getResourcePlugin()->willReturn($resource->reveal());
$config->getCacheContexts()->willReturn([]);
$config->getCacheTags()->willReturn([]);
$config->getCacheMaxAge()->willReturn(12);
$this->entityStorage->load('restplugin')->willReturn($config->reveal());
$response = new ResourceResponse($data);
$resource->get(NULL, $request)
->willReturn($response);
$handler_response = $this->requestHandler->handle($route_match, $request);
// Content is a serialized version of the data we provided.
$this->assertEquals(json_encode($data), $handler_response->getContent());
$this->assertEquals($expected_response !== FALSE ? $expected_response : json_encode($data), $handler_response->getContent());
}
public function providerTestSerialization() {
return [
[NULL],
// The default data for \Drupal\rest\ResourceResponse.
[NULL, ''],
[''],
['string'],
['Complex \ string $%^&@ with unicode ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ'],
@ -124,6 +137,203 @@ class RequestHandlerTest extends KernelTestBase {
];
}
/**
* @covers ::getResponseFormat
*
* Note this does *not* need to test formats being requested that are not
* accepted by the server, because the routing system would have already
* prevented those from reaching RequestHandler.
*
* @param string[] $methods
* The HTTP methods to test.
* @param string[] $supported_formats
* The supported formats for the REST route to be tested.
* @param string|false $request_format
* The value for the ?_format URL query argument, if any.
* @param string[] $request_headers
* The request headers to send, if any.
* @param string|null $request_body
* The request body to send, if any.
* @param string|null $expected_response_content_type
* The expected MIME type of the response, if any.
* @param string $expected_response_content
* The expected content of the response.
*
* @dataProvider providerTestResponseFormat
*/
public function testResponseFormat($methods, array $supported_formats, $request_format, array $request_headers, $request_body, $expected_response_content_type, $expected_response_content) {
$rest_config_name = $this->randomMachineName();
$parameters = [];
if ($request_format !== FALSE) {
$parameters['_format'] = $request_format;
}
foreach ($request_headers as $key => $value) {
unset($request_headers[$key]);
$key = strtoupper(str_replace('-', '_', $key));
$request_headers[$key] = $value;
}
foreach ($methods as $method) {
$request = Request::create('/rest/test', $method, $parameters, [], [], $request_headers, $request_body);
$route_requirement_key_format = $request->isMethodSafe() ? '_format' : '_content_type_format';
$route_match = new RouteMatch('test', new Route('/rest/test', ['_rest_resource_config' => $rest_config_name], [$route_requirement_key_format => implode('|', $supported_formats)]));
$resource = $this->prophesize(StubRequestHandlerResourcePlugin::class);
// Mock the configuration.
$config = $this->prophesize(RestResourceConfigInterface::class);
$config->getFormats($method)->willReturn($supported_formats);
$config->getResourcePlugin()->willReturn($resource->reveal());
$config->getCacheContexts()->willReturn([]);
$config->getCacheTags()->willReturn([]);
$config->getCacheMaxAge()->willReturn(12);
$this->entityStorage->load($rest_config_name)->willReturn($config->reveal());
// Mock the resource plugin.
$response = new ResourceResponse($method !== 'DELETE' ? ['REST' => 'Drupal'] : NULL);
$resource->getPluginDefinition()->willReturn([]);
$method_prophecy = new MethodProphecy($resource, strtolower($method), [Argument::any(), $request]);
$method_prophecy->willReturn($response);
$resource->addMethodProphecy($method_prophecy);
// Test the request handler.
$handler_response = $this->requestHandler->handle($route_match, $request);
$this->assertSame($expected_response_content_type, $handler_response->headers->get('Content-Type'));
$this->assertEquals($expected_response_content, $handler_response->getContent());
}
}
/**
* @return array
* 0. methods to test
* 1. supported formats for route requirements
* 2. request format
* 3. request headers
* 4. request body
* 5. expected response content type
* 6. expected response body
*/
public function providerTestResponseFormat() {
$json_encoded = Json::encode(['REST' => 'Drupal']);
$xml_encoded = "<?xml version=\"1.0\"?>\n<response><REST>Drupal</REST></response>\n";
$safe_method_test_cases = [
'safe methods: client requested format (JSON)' => [
// @todo add 'HEAD' in https://www.drupal.org/node/2752325
['GET'],
['xml', 'json'],
'json',
[],
NULL,
'application/json',
$json_encoded,
],
'safe methods: client requested format (XML)' => [
// @todo add 'HEAD' in https://www.drupal.org/node/2752325
['GET'],
['xml', 'json'],
'xml',
[],
NULL,
'text/xml',
$xml_encoded,
],
'safe methods: client requested no format: response should use the first configured format (JSON)' => [
// @todo add 'HEAD' in https://www.drupal.org/node/2752325
['GET'],
['json', 'xml'],
FALSE,
[],
NULL,
'application/json',
$json_encoded,
],
'safe methods: client requested no format: response should use the first configured format (XML)' => [
// @todo add 'HEAD' in https://www.drupal.org/node/2752325
['GET'],
['xml', 'json'],
FALSE,
[],
NULL,
'text/xml',
$xml_encoded,
],
];
$unsafe_method_bodied_test_cases = [
'unsafe methods with response (POST, PATCH): client requested no format, response should use request body format (JSON)' => [
['POST', 'PATCH'],
['xml', 'json'],
FALSE,
['Content-Type' => 'application/json'],
$json_encoded,
'application/json',
$json_encoded,
],
'unsafe methods with response (POST, PATCH): client requested no format, response should use request body format (XML)' => [
['POST', 'PATCH'],
['xml', 'json'],
FALSE,
['Content-Type' => 'text/xml'],
$xml_encoded,
'text/xml',
$xml_encoded,
],
'unsafe methods with response (POST, PATCH): client requested format other than request body format (JSON): response format should use requested format (XML)' => [
['POST', 'PATCH'],
['xml', 'json'],
'xml',
['Content-Type' => 'application/json'],
$json_encoded,
'text/xml',
$xml_encoded,
],
'unsafe methods with response (POST, PATCH): client requested format other than request body format (XML), but is allowed for the request body (JSON)' => [
['POST', 'PATCH'],
['xml', 'json'],
'json',
['Content-Type' => 'text/xml'],
$xml_encoded,
'application/json',
$json_encoded,
],
];
$unsafe_method_bodyless_test_cases = [
'unsafe methods with response bodies (DELETE): client requested no format, response should have no format' => [
['DELETE'],
['xml', 'json'],
FALSE,
['Content-Type' => 'application/json'],
$json_encoded,
NULL,
'',
],
'unsafe methods with response bodies (DELETE): client requested format (XML), response should have no format' => [
['DELETE'],
['xml', 'json'],
'xml',
['Content-Type' => 'application/json'],
$json_encoded,
NULL,
'',
],
'unsafe methods with response bodies (DELETE): client requested format (JSON), response should have no format' => [
['DELETE'],
['xml', 'json'],
'json',
['Content-Type' => 'application/json'],
$json_encoded,
NULL,
'',
],
];
return $safe_method_test_cases + $unsafe_method_bodied_test_cases + $unsafe_method_bodyless_test_cases;
}
}
/**
@ -132,6 +342,8 @@ class RequestHandlerTest extends KernelTestBase {
class StubRequestHandlerResourcePlugin extends ResourceBase {
function get() {}
function post() {}
function patch() {}
function delete() {}
}

View file

@ -14,7 +14,7 @@ class RestLinkManagerTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['rest', 'rest_test', 'system'];
public static $modules = ['serialization', 'rest', 'rest_test', 'system'];
/**
* {@inheritdoc}

View file

@ -0,0 +1,69 @@
<?php
namespace Drupal\Tests\rest\Kernel\Views;
use Drupal\rest\Plugin\views\display\RestExport;
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
use Drupal\views\Entity\View;
use Drupal\views\Tests\ViewTestData;
/**
* Tests the REST export view display plugin.
*
* @coversDefaultClass \Drupal\rest\Plugin\views\display\RestExport
*
* @group rest
*/
class RestExportTest extends ViewsKernelTestBase {
/**
* {@inheritdoc}
*/
public static $testViews = ['test_serializer_display_entity'];
/**
* {@inheritdoc}
*/
public static $modules = ['rest_test_views', 'serialization', 'rest', 'entity_test'];
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
ViewTestData::createTestViews(get_class($this), ['rest_test_views']);
$this->installEntitySchema('entity_test');
}
/**
* @covers ::buildResponse
*/
public function testBuildResponse() {
/** @var \Drupal\views\Entity\View $view */
$view = View::load('test_serializer_display_entity');
$display = &$view->getDisplay('rest_export_1');
$display['display_options']['defaults']['style'] = FALSE;
$display['display_options']['style']['type'] = 'serializer';
$display['display_options']['style']['options']['formats'] = ['json', 'xml'];
$view->save();
// No custom header should be set yet.
$response = RestExport::buildResponse('test_serializer_display_entity', 'rest_export_1', []);
$this->assertFalse($response->headers->get('Custom-Header'));
// Clear render cache.
/** @var \Drupal\Core\Cache\MemoryBackend $render_cache */
$render_cache = $this->container->get('cache_factory')->get('render');
$render_cache->deleteAll();
// A custom header should now be added.
// @see rest_test_views_views_post_execute()
$header = $this->randomString();
$this->container->get('state')->set('rest_test_views_set_header', $header);
$response = RestExport::buildResponse('test_serializer_display_entity', 'rest_export_1', []);
$this->assertEquals($header, $response->headers->get('Custom-Header'));
}
}

View file

@ -0,0 +1,61 @@
<?php
namespace Drupal\Tests\rest\Kernel\Views;
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
use Drupal\views\Entity\View;
use Drupal\views\Tests\ViewTestData;
/**
* @coversDefaultClass \Drupal\rest\Plugin\views\style\Serializer
* @group views
*/
class StyleSerializerKernelTest extends ViewsKernelTestBase {
/**
* {@inheritdoc}
*/
public static $testViews = ['test_serializer_display_entity'];
/**
* {@inheritdoc}
*/
public static $modules = ['rest_test_views', 'serialization', 'rest'];
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
ViewTestData::createTestViews(get_class($this), ['rest_test_views']);
}
/**
* @covers ::calculateDependencies
*/
public function testCalculateDepenencies() {
/** @var \Drupal\views\Entity\View $view */
$view = View::load('test_serializer_display_entity');
$display = &$view->getDisplay('rest_export_1');
$display['display_options']['defaults']['style'] = FALSE;
$display['display_options']['style']['type'] = 'serializer';
$display['display_options']['style']['options']['formats'] = ['json', 'xml'];
$view->save();
$view->calculateDependencies();
$this->assertEquals(['module' => ['rest', 'serialization', 'user']], $view->getDependencies());
\Drupal::service('module_installer')->install(['hal']);
$view = View::load('test_serializer_display_entity');
$display = &$view->getDisplay('rest_export_1');
$display['display_options']['style']['options']['formats'] = ['json', 'xml', 'hal_json'];
$view->save();
$view->calculateDependencies();
$this->assertEquals(['module' => ['hal', 'rest', 'serialization', 'user']], $view->getDependencies());
}
}

View file

@ -67,6 +67,8 @@ class CollectRoutesTest extends UnitTestCase {
->getMock();
$container->set('router.route_provider', $route_provider);
$container->setParameter('authentication_providers', ['basic_auth' => 'basic_auth']);
$state = $this->getMock('\Drupal\Core\State\StateInterface');
$container->set('state', $state);
@ -76,6 +78,12 @@ class CollectRoutesTest extends UnitTestCase {
$container->set('plugin.manager.views.style', $style_manager);
$container->set('renderer', $this->getMock('Drupal\Core\Render\RendererInterface'));
$authentication_collector = $this->getMock('\Drupal\Core\Authentication\AuthenticationCollectorInterface');
$container->set('authentication_collector', $authentication_collector);
$authentication_collector->expects($this->any())
->method('getSortedProviders')
->will($this->returnValue(['basic_auth' => 'data', 'cookie' => 'data']));
\Drupal::setContainer($container);
$this->restExport = RestExport::create($container, array(), "test_routes", array());
@ -87,6 +95,9 @@ class CollectRoutesTest extends UnitTestCase {
// Set the style option.
$this->restExport->setOption('style', array('type' => 'serializer'));
// Set the auth option.
$this->restExport->setOption('auth', ['basic_auth']);
$display_manager->expects($this->once())
->method('getDefinition')
->will($this->returnValue(array('id' => 'test', 'provider' => 'test')));
@ -132,6 +143,11 @@ class CollectRoutesTest extends UnitTestCase {
$this->assertEquals(count($requirements_1), 0, 'First route has no requirement.');
$this->assertEquals(count($requirements_2), 2, 'Views route with rest export had the format and method requirements added.');
// Check auth options.
$auth = $this->routes->get('view.test_view.page_1')->getOption('_auth');
$this->assertEquals(count($auth), 1, 'View route with rest export has an auth option added');
$this->assertEquals($auth[0], 'basic_auth', 'View route with rest export has the correct auth option added');
}
}

View file

@ -68,7 +68,7 @@ class SerializerTest extends UnitTestCase {
->willReturn()
->shouldBeCalled();
$view_serializer_style = new Serializer([], 'dummy_serializer', [], $mock_serializer->reveal(), ['json', 'xml']);
$view_serializer_style = new Serializer([], 'dummy_serializer', [], $mock_serializer->reveal(), ['json', 'xml'], ['json' => 'serialization', 'xml' => 'serialization']);
$view_serializer_style->options = ['formats' => ['xml', 'json']];
$view_serializer_style->view = $this->view;
$view_serializer_style->displayHandler = $this->displayHandler;