upgrades core to 8.4.2
This commit is contained in:
+63
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Test fixture for \Drupal\rest\Tests\Update\RestExportAuthCorrectionUpdateTest.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Serialization\Yaml;
|
||||
|
||||
$connection = Database::getConnection();
|
||||
|
||||
// Set the schema version.
|
||||
$connection->insert('key_value')
|
||||
->fields([
|
||||
'collection' => 'system.schema',
|
||||
'name' => 'rest',
|
||||
'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();
|
||||
|
||||
$connection->insert('config')
|
||||
->fields([
|
||||
'name' => 'rest.settings',
|
||||
'data' => serialize([
|
||||
'link_domain' => '~',
|
||||
]),
|
||||
'collection' => '',
|
||||
])
|
||||
->execute();
|
||||
|
||||
$connection->insert('config')
|
||||
->fields([
|
||||
'name' => 'views.view.rest_export_with_authorization_correction',
|
||||
])
|
||||
->execute();
|
||||
|
||||
$connection->merge('config')
|
||||
->condition('name', 'views.view.rest_export_with_authorization_correction')
|
||||
->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_correction.yml'))),
|
||||
])
|
||||
->execute();
|
||||
@@ -6,8 +6,8 @@ package: Testing
|
||||
dependencies:
|
||||
- config_test
|
||||
|
||||
# Information added by Drupal.org packaging script on 2017-08-16
|
||||
version: '8.3.7'
|
||||
# Information added by Drupal.org packaging script on 2017-11-03
|
||||
version: '8.4.2'
|
||||
core: '8.x'
|
||||
project: 'drupal'
|
||||
datestamp: 1502903957
|
||||
datestamp: 1509719929
|
||||
|
||||
@@ -7,8 +7,8 @@ package: Testing
|
||||
dependencies:
|
||||
- rest
|
||||
|
||||
# Information added by Drupal.org packaging script on 2017-08-16
|
||||
version: '8.3.7'
|
||||
# Information added by Drupal.org packaging script on 2017-11-03
|
||||
version: '8.4.2'
|
||||
core: '8.x'
|
||||
project: 'drupal'
|
||||
datestamp: 1502903957
|
||||
datestamp: 1509719929
|
||||
|
||||
@@ -8,8 +8,8 @@ dependencies:
|
||||
- rest
|
||||
- views
|
||||
|
||||
# Information added by Drupal.org packaging script on 2017-08-16
|
||||
version: '8.3.7'
|
||||
# Information added by Drupal.org packaging script on 2017-11-03
|
||||
version: '8.4.2'
|
||||
core: '8.x'
|
||||
project: 'drupal'
|
||||
datestamp: 1502903957
|
||||
datestamp: 1509719929
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional;
|
||||
|
||||
/**
|
||||
* Trait for ResourceTestBase subclasses formatting expected timestamp data.
|
||||
*/
|
||||
trait BcTimestampNormalizerUnixTestTrait {
|
||||
|
||||
/**
|
||||
* Formats a UNIX timestamp.
|
||||
*
|
||||
* Depending on the 'bc_timestamp_normalizer_unix' setting. The return will be
|
||||
* an RFC3339 date string or the same timestamp that was passed in.
|
||||
*
|
||||
* @param int $timestamp
|
||||
* The timestamp value to format.
|
||||
*
|
||||
* @return string|int
|
||||
* The formatted RFC3339 date string or UNIX timestamp.
|
||||
*
|
||||
* @see \Drupal\serialization\Normalizer\TimestampItemNormalizer
|
||||
*/
|
||||
protected function formatExpectedTimestampItemValues($timestamp) {
|
||||
// If the setting is enabled, just return the timestamp as-is now.
|
||||
if ($this->config('serialization.settings')->get('bc_timestamp_normalizer_unix')) {
|
||||
return ['value' => $timestamp];
|
||||
}
|
||||
|
||||
// Otherwise, format the date string to the same that
|
||||
// \Drupal\serialization\Normalizer\TimestampItemNormalizer will produce.
|
||||
$date = new \DateTime();
|
||||
$date->setTimestamp($timestamp);
|
||||
$date->setTimezone(new \DateTimeZone('UTC'));
|
||||
|
||||
// Format is also added to the expected return values.
|
||||
return [
|
||||
'value' => $date->format(\DateTime::RFC3339),
|
||||
'format' => \DateTime::RFC3339,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -71,7 +71,7 @@ trait CookieResourceTestTrait {
|
||||
$this->sessionCookie = explode(';', $response->getHeader('Set-Cookie')[0], 2)[0];
|
||||
|
||||
// Parse and store the CSRF token and logout token.
|
||||
$data = $this->serializer->decode((string)$response->getBody(), static::$format);
|
||||
$data = $this->serializer->decode((string) $response->getBody(), static::$format);
|
||||
$this->csrfToken = $data['csrf_token'];
|
||||
$this->logoutToken = $data['logout_token'];
|
||||
}
|
||||
|
||||
+1
-3
@@ -122,9 +122,7 @@ abstract class BlockResourceTestBase extends EntityResourceTestBase {
|
||||
protected function getExpectedCacheTags() {
|
||||
// Because the 'user.permissions' cache context is missing, the cache tag
|
||||
// for the anonymous user role is never added automatically.
|
||||
return array_values(array_filter(parent::getExpectedCacheTags(), function ($tag) {
|
||||
return $tag !== 'config:user.role.anonymous';
|
||||
}));
|
||||
return array_values(array_diff(parent::getExpectedCacheTags(), ['config:user.role.anonymous']));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+15
-19
@@ -6,13 +6,14 @@ use Drupal\comment\Entity\Comment;
|
||||
use Drupal\comment\Entity\CommentType;
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
|
||||
abstract class CommentResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
use CommentTestTrait, BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -148,14 +149,10 @@ abstract class CommentResourceTestBase extends EntityResourceTestBase {
|
||||
],
|
||||
],
|
||||
'created' => [
|
||||
[
|
||||
'value' => 123456789,
|
||||
],
|
||||
$this->formatExpectedTimestampItemValues(123456789),
|
||||
],
|
||||
'changed' => [
|
||||
[
|
||||
'value' => $this->entity->getChangedTime(),
|
||||
],
|
||||
$this->formatExpectedTimestampItemValues($this->entity->getChangedTime()),
|
||||
],
|
||||
'default_langcode' => [
|
||||
[
|
||||
@@ -222,7 +219,7 @@ abstract class CommentResourceTestBase extends EntityResourceTestBase {
|
||||
],
|
||||
'entity_id' => [
|
||||
[
|
||||
'target_id' => EntityTest::load(1)->id(),
|
||||
'target_id' => (int) EntityTest::load(1)->id(),
|
||||
],
|
||||
],
|
||||
'field_name' => [
|
||||
@@ -280,9 +277,9 @@ abstract class CommentResourceTestBase extends EntityResourceTestBase {
|
||||
$response = $this->request('POST', $url, $request_options);
|
||||
// @todo Uncomment, remove next 3 lines in https://www.drupal.org/node/2820364.
|
||||
$this->assertSame(500, $response->getStatusCode());
|
||||
$this->assertSame(['application/json'], $response->getHeader('Content-Type'));
|
||||
$this->assertSame('{"message":"A fatal error occurred: Internal Server Error"}', (string) $response->getBody());
|
||||
//$this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response);
|
||||
$this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
|
||||
$this->assertStringStartsWith('The website encountered an unexpected error. Please try again later.</br></br><em class="placeholder">Symfony\Component\HttpKernel\Exception\HttpException</em>: Internal Server Error in <em class="placeholder">Drupal\rest\Plugin\rest\resource\EntityResource->post()</em>', (string) $response->getBody());
|
||||
// $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response);
|
||||
|
||||
// DX: 422 when missing 'entity_id' field.
|
||||
$request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['entity_id' => TRUE]), static::$format);
|
||||
@@ -291,23 +288,22 @@ abstract class CommentResourceTestBase extends EntityResourceTestBase {
|
||||
try {
|
||||
$response = $this->request('POST', $url, $request_options);
|
||||
// This happens on DrupalCI.
|
||||
//$this->assertSame(500, $response->getStatusCode());
|
||||
// $this->assertSame(500, $response->getStatusCode());
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// This happens on Wim's local machine.
|
||||
//$this->assertSame("Error: Call to a member function get() on null\nDrupal\\comment\\Plugin\\Validation\\Constraint\\CommentNameConstraintValidator->getAnonymousContactDetailsSetting()() (Line: 96)\n", $e->getMessage());
|
||||
// $this->assertSame("Error: Call to a member function get() on null\nDrupal\\comment\\Plugin\\Validation\\Constraint\\CommentNameConstraintValidator->getAnonymousContactDetailsSetting()() (Line: 96)\n", $e->getMessage());
|
||||
}
|
||||
//$response = $this->request('POST', $url, $request_options);
|
||||
//$this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response);
|
||||
// $response = $this->request('POST', $url, $request_options);
|
||||
// $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response);
|
||||
|
||||
// DX: 422 when missing 'entity_type' field.
|
||||
$request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['field_name' => TRUE]), static::$format);
|
||||
$response = $this->request('POST', $url, $request_options);
|
||||
// @todo Uncomment, remove next 3 lines in https://www.drupal.org/node/2820364.
|
||||
// @todo Uncomment, remove next 2 lines in https://www.drupal.org/node/2820364.
|
||||
$this->assertSame(500, $response->getStatusCode());
|
||||
$this->assertSame(['application/json'], $response->getHeader('Content-Type'));
|
||||
$this->assertSame('{"message":"A fatal error occurred: Field is unknown."}', (string) $response->getBody());
|
||||
//$this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nfield_name: This value should not be null.\n", $response);
|
||||
$this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
|
||||
// $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nfield_name: This value should not be null.\n", $response);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ContactForm;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ContactFormJsonAnonTest extends ContactFormResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ContactForm;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ContactFormJsonBasicAuthTest extends ContactFormResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ContactForm;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ContactFormJsonCookieTest extends ContactFormResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ContactForm;
|
||||
|
||||
use Drupal\contact\Entity\ContactForm;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
abstract class ContactFormResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['contact'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'contact_form';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $patchProtectedFieldNames = [];
|
||||
|
||||
/**
|
||||
* @var \Drupal\contact\Entity\ContactForm
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$this->grantPermissionsToTestedRole(['access site-wide contact form']);
|
||||
default:
|
||||
$this->grantPermissionsToTestedRole(['administer contact forms']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$contact_form = ContactForm::create([
|
||||
'id' => 'llama',
|
||||
'label' => 'Llama',
|
||||
'message' => 'Let us know what you think about llamas',
|
||||
'reply' => 'Llamas are indeed awesome!',
|
||||
'recipients' => [
|
||||
'llama@example.com',
|
||||
'contact@example.com',
|
||||
],
|
||||
]);
|
||||
$contact_form->save();
|
||||
|
||||
return $contact_form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'dependencies' => [],
|
||||
'id' => 'llama',
|
||||
'label' => 'Llama',
|
||||
'langcode' => 'en',
|
||||
'message' => 'Let us know what you think about llamas',
|
||||
'recipients' => [
|
||||
'llama@example.com',
|
||||
'contact@example.com',
|
||||
],
|
||||
'redirect' => NULL,
|
||||
'reply' => 'Llamas are indeed awesome!',
|
||||
'status' => TRUE,
|
||||
'uuid' => $this->entity->uuid(),
|
||||
'weight' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
|
||||
return "The 'access site-wide contact form' permission is required.";
|
||||
}
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\DateFormat;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class DateFormatJsonAnonTest extends DateFormatResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\DateFormat;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class DateFormatJsonBasicAuthTest extends DateFormatResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\DateFormat;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class DateFormatJsonCookieTest extends DateFormatResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\DateFormat;
|
||||
|
||||
use Drupal\Core\Datetime\Entity\DateFormat;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
/**
|
||||
* ResourceTestBase for DateFormat entity.
|
||||
*/
|
||||
abstract class DateFormatResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'date_format';
|
||||
|
||||
/**
|
||||
* The DateFormat entity.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer site configuration']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
// Create a date format.
|
||||
$date_format = DateFormat::create([
|
||||
'id' => 'llama',
|
||||
'label' => 'Llama',
|
||||
'pattern' => 'F d, Y',
|
||||
]);
|
||||
|
||||
$date_format->save();
|
||||
|
||||
return $date_format;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'dependencies' => [],
|
||||
'id' => 'llama',
|
||||
'label' => 'Llama',
|
||||
'langcode' => 'en',
|
||||
'locked' => FALSE,
|
||||
'pattern' => 'F d, Y',
|
||||
'status' => TRUE,
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityFormMode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class EntityFormModeJsonAnonTest extends EntityFormModeResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityFormMode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class EntityFormModeJsonBasicAuthTest extends EntityFormModeResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityFormMode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class EntityFormModeJsonCookieTest extends EntityFormModeResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityFormMode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\Core\Entity\Entity\EntityFormMode;
|
||||
|
||||
abstract class EntityFormModeResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @todo: Remove 'field_ui' when https://www.drupal.org/node/2867266.
|
||||
*/
|
||||
public static $modules = ['user', 'field_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'entity_form_mode';
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Entity\EntityFormModeInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer display modes']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$entity_form_mode = EntityFormMode::create([
|
||||
'id' => 'user.test',
|
||||
'label' => 'Test',
|
||||
'targetEntityType' => 'user',
|
||||
]);
|
||||
$entity_form_mode->save();
|
||||
return $entity_form_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'cache' => TRUE,
|
||||
'dependencies' => [
|
||||
'module' => [
|
||||
'user',
|
||||
],
|
||||
],
|
||||
'id' => 'user.test',
|
||||
'label' => 'Test',
|
||||
'langcode' => 'en',
|
||||
'status' => TRUE,
|
||||
'targetEntityType' => 'user',
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,11 +4,13 @@ namespace Drupal\Tests\rest\Functional\EntityResource;
|
||||
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheableResponseInterface;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\rest\ResourceResponseInterface;
|
||||
use Drupal\Tests\rest\Functional\ResourceTestBase;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
@@ -149,7 +151,6 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
// Calculate REST Resource config entity ID.
|
||||
static::$resourceConfigId = 'entity.' . static::$entityTypeId;
|
||||
|
||||
$this->serializer = $this->container->get('serializer');
|
||||
$this->entityStorage = $this->container->get('entity_type.manager')
|
||||
->getStorage(static::$entityTypeId);
|
||||
|
||||
@@ -229,7 +230,7 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
|
||||
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
|
||||
return $this->getExpectedBCUnauthorizedAccessMessage($method);
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
|
||||
$permission = $this->entity->getEntityType()->getAdminPermission();
|
||||
@@ -253,13 +254,6 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
return "$message.";
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedBcUnauthorizedAccessMessage($method) {
|
||||
return "The 'restful " . strtolower($method) . " entity:" . $this->entity->getEntityTypeId() . "' permission is required.";
|
||||
}
|
||||
|
||||
/**
|
||||
* The expected cache tags for the GET/HEAD response of the test entity.
|
||||
*
|
||||
@@ -334,7 +328,6 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$url->setOption('query', []);
|
||||
|
||||
|
||||
|
||||
// DX: 406 when ?_format is missing, except when requesting a canonical HTML
|
||||
// route.
|
||||
$response = $this->request('GET', $url, $request_options);
|
||||
@@ -379,13 +372,24 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$this->assertArrayNotHasKey('Link', $response->getHeaders());
|
||||
|
||||
|
||||
|
||||
$this->setUpAuthorization('GET');
|
||||
|
||||
|
||||
// 200 for well-formed HEAD request.
|
||||
$response = $this->request('HEAD', $url, $request_options);
|
||||
$this->assertResourceResponse(200, '', $response);
|
||||
// @todo Entity resources with URLs that begin with '/admin/' are marked as
|
||||
// administrative (see https://www.drupal.org/node/2874938), which
|
||||
// excludes them from Dynamic Page Cache (see
|
||||
// https://www.drupal.org/node/2877528). When either of those issues is
|
||||
// fixed, remove the if-test and the 'else' block.
|
||||
if (strpos($this->entity->getEntityType()->getLinkTemplate('canonical'), '/admin/') !== 0) {
|
||||
$this->assertTrue($response->hasHeader('X-Drupal-Dynamic-Cache'));
|
||||
$this->assertSame(['MISS'], $response->getHeader('X-Drupal-Dynamic-Cache'));
|
||||
}
|
||||
else {
|
||||
$this->assertFalse($response->hasHeader('X-Drupal-Dynamic-Cache'));
|
||||
}
|
||||
if (!$this->account) {
|
||||
$this->assertSame(['MISS'], $response->getHeader('X-Drupal-Cache'));
|
||||
}
|
||||
@@ -395,13 +399,53 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$head_headers = $response->getHeaders();
|
||||
|
||||
// 200 for well-formed GET request. Page Cache hit because of HEAD request.
|
||||
// Same for Dynamic Page Cache hit.
|
||||
$response = $this->request('GET', $url, $request_options);
|
||||
$this->assertResourceResponse(200, FALSE, $response);
|
||||
if (!static::$auth) {
|
||||
$this->assertSame(['HIT'], $response->getHeader('X-Drupal-Cache'));
|
||||
// @todo Entity resources with URLs that begin with '/admin/' are marked as
|
||||
// administrative (see https://www.drupal.org/node/2874938), which
|
||||
// excludes them from Dynamic Page Cache (see
|
||||
// https://www.drupal.org/node/2877528). When either of those issues is
|
||||
// fixed, remove the if-test and the 'else' block.
|
||||
if (strpos($this->entity->getEntityType()->getLinkTemplate('canonical'), '/admin/') !== 0) {
|
||||
$this->assertTrue($response->hasHeader('X-Drupal-Dynamic-Cache'));
|
||||
if (!static::$auth) {
|
||||
$this->assertSame(['HIT'], $response->getHeader('X-Drupal-Cache'));
|
||||
$this->assertSame(['MISS'], $response->getHeader('X-Drupal-Dynamic-Cache'));
|
||||
}
|
||||
else {
|
||||
$this->assertFalse($response->hasHeader('X-Drupal-Cache'));
|
||||
$this->assertSame(['HIT'], $response->getHeader('X-Drupal-Dynamic-Cache'));
|
||||
// Assert that Dynamic Page Cache did not store a ResourceResponse object,
|
||||
// which needs serialization after every cache hit. Instead, it should
|
||||
// contain a flattened response. Otherwise performance suffers.
|
||||
// @see \Drupal\rest\EventSubscriber\ResourceResponseSubscriber::flattenResponse()
|
||||
$cache_items = $this->container->get('database')
|
||||
->query("SELECT cid, data FROM {cache_dynamic_page_cache} WHERE cid LIKE :pattern", [
|
||||
':pattern' => '%[route]=rest.%',
|
||||
])
|
||||
->fetchAllAssoc('cid');
|
||||
$this->assertCount(2, $cache_items);
|
||||
$found_cache_redirect = FALSE;
|
||||
$found_cached_response = FALSE;
|
||||
foreach ($cache_items as $cid => $cache_item) {
|
||||
$cached_data = unserialize($cache_item->data);
|
||||
if (!isset($cached_data['#cache_redirect'])) {
|
||||
$found_cached_response = TRUE;
|
||||
$cached_response = $cached_data['#response'];
|
||||
$this->assertNotInstanceOf(ResourceResponseInterface::class, $cached_response);
|
||||
$this->assertInstanceOf(CacheableResponseInterface::class, $cached_response);
|
||||
}
|
||||
else {
|
||||
$found_cache_redirect = TRUE;
|
||||
}
|
||||
}
|
||||
$this->assertTrue($found_cache_redirect);
|
||||
$this->assertTrue($found_cached_response);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->assertFalse($response->hasHeader('X-Drupal-Cache'));
|
||||
$this->assertFalse($response->hasHeader('X-Drupal-Dynamic-Cache'));
|
||||
}
|
||||
$cache_tags_header_value = $response->getHeader('X-Drupal-Cache-Tags')[0];
|
||||
$this->assertEquals($this->getExpectedCacheTags(), empty($cache_tags_header_value) ? [] : explode(' ', $cache_tags_header_value));
|
||||
@@ -411,9 +455,9 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
// for the keys with the array order the same (it needs to match with
|
||||
// identical comparison).
|
||||
$expected = $this->getExpectedNormalizedEntity();
|
||||
ksort($expected);
|
||||
static::recursiveKSort($expected);
|
||||
$actual = $this->serializer->decode((string) $response->getBody(), static::$format);
|
||||
ksort($actual);
|
||||
static::recursiveKSort($actual);
|
||||
$this->assertSame($expected, $actual);
|
||||
|
||||
// Not only assert the normalization, also assert deserialization of the
|
||||
@@ -424,11 +468,11 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
if ($this->entity->getEntityType()->getLinkTemplates()) {
|
||||
$this->assertArrayHasKey('Link', $response->getHeaders());
|
||||
$link_relation_type_manager = $this->container->get('plugin.manager.link_relation_type');
|
||||
$expected_link_relation_headers = array_map(function ($rel) use ($link_relation_type_manager) {
|
||||
$definition = $link_relation_type_manager->getDefinition($rel, FALSE);
|
||||
return (!empty($definition['uri']))
|
||||
? $definition['uri']
|
||||
: $rel;
|
||||
$expected_link_relation_headers = array_map(function ($relation_name) use ($link_relation_type_manager) {
|
||||
$link_relation_type = $link_relation_type_manager->createInstance($relation_name);
|
||||
return $link_relation_type->isRegistered()
|
||||
? $link_relation_type->getRegisteredName()
|
||||
: $link_relation_type->getExtensionUri();
|
||||
}, array_keys($this->entity->getEntityType()->getLinkTemplates()));
|
||||
$parse_rel_from_link_header = function ($value) use ($link_relation_type_manager) {
|
||||
$matches = [];
|
||||
@@ -453,12 +497,14 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
}
|
||||
$this->assertSame($get_headers, $head_headers);
|
||||
|
||||
// BC: serialization_update_8302().
|
||||
// Only run this for fieldable entities. It doesn't make sense for config
|
||||
// entities as config values are already casted. They also run through the
|
||||
// ConfigEntityNormalizer, which doesn't deal with fields individually.
|
||||
if ($this->entity instanceof FieldableEntityInterface) {
|
||||
// Test primitive data casting BC (strings).
|
||||
$this->config('serialization.settings')->set('bc_primitives_as_strings', TRUE)->save(TRUE);
|
||||
// Rebuild the container so new config is reflected in the removal of the
|
||||
// Rebuild the container so new config is reflected in the addition of the
|
||||
// PrimitiveDataNormalizer.
|
||||
$this->rebuildAll();
|
||||
|
||||
@@ -474,10 +520,48 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
// Config entities are not affected.
|
||||
// @see \Drupal\serialization\Normalizer\ConfigEntityNormalizer::normalize()
|
||||
$expected = static::castToString($expected);
|
||||
ksort($expected);
|
||||
static::recursiveKSort($expected);
|
||||
$actual = $this->serializer->decode((string) $response->getBody(), static::$format);
|
||||
ksort($actual);
|
||||
static::recursiveKSort($actual);
|
||||
$this->assertSame($expected, $actual);
|
||||
|
||||
// Reset the config value and rebuild.
|
||||
$this->config('serialization.settings')->set('bc_primitives_as_strings', FALSE)->save(TRUE);
|
||||
$this->rebuildAll();
|
||||
}
|
||||
|
||||
// BC: serialization_update_8401().
|
||||
// Only run this for fieldable entities. It doesn't make sense for config
|
||||
// entities as config values always use the raw values (as per the config
|
||||
// schema), returned directly from the ConfigEntityNormalizer, which
|
||||
// doesn't deal with fields individually.
|
||||
if ($this->entity instanceof FieldableEntityInterface) {
|
||||
// Test the BC settings for timestamp values.
|
||||
$this->config('serialization.settings')->set('bc_timestamp_normalizer_unix', TRUE)->save(TRUE);
|
||||
// Rebuild the container so new config is reflected in the addition of the
|
||||
// TimestampItemNormalizer.
|
||||
$this->rebuildAll();
|
||||
|
||||
|
||||
$response = $this->request('GET', $url, $request_options);
|
||||
$this->assertResourceResponse(200, FALSE, $response);
|
||||
|
||||
|
||||
// This ensures the BC layer for bc_timestamp_normalizer_unix works as
|
||||
// expected. This method should be using
|
||||
// ::formatExpectedTimestampValue() to generate the timestamp value. This
|
||||
// will take into account the above config setting.
|
||||
$expected = $this->getExpectedNormalizedEntity();
|
||||
// Config entities are not affected.
|
||||
// @see \Drupal\serialization\Normalizer\ConfigEntityNormalizer::normalize()
|
||||
static::recursiveKSort($expected);
|
||||
$actual = $this->serializer->decode((string) $response->getBody(), static::$format);
|
||||
static::recursiveKSort($actual);
|
||||
$this->assertSame($expected, $actual);
|
||||
|
||||
// Reset the config value and rebuild.
|
||||
$this->config('serialization.settings')->set('bc_timestamp_normalizer_unix', FALSE)->save(TRUE);
|
||||
$this->rebuildAll();
|
||||
}
|
||||
|
||||
|
||||
@@ -531,17 +615,17 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
// DX: 406 when requesting unsupported format.
|
||||
$response = $this->request('GET', $url, $request_options);
|
||||
$this->assert406Response($response);
|
||||
$this->assertNotSame([static::$mimeType], $response->getHeader('Content-Type'));
|
||||
$this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
|
||||
|
||||
|
||||
$request_options[RequestOptions::HEADERS]['Accept'] = static::$mimeType;
|
||||
|
||||
|
||||
// DX: 406 when requesting unsupported format but specifying Accept header.
|
||||
// @todo Update in https://www.drupal.org/node/2825347.
|
||||
// DX: 406 when requesting unsupported format but specifying Accept header:
|
||||
// should result in a text/plain response.
|
||||
$response = $this->request('GET', $url, $request_options);
|
||||
$this->assert406Response($response);
|
||||
$this->assertSame(['application/json'], $response->getHeader('Content-Type'));
|
||||
$this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
|
||||
|
||||
|
||||
$url = Url::fromRoute('rest.entity.' . static::$entityTypeId . '.GET.' . static::$format);
|
||||
@@ -580,6 +664,27 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
return $normalization;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively sorts an array by key.
|
||||
*
|
||||
* @param array $array
|
||||
* An array to sort.
|
||||
*
|
||||
* @return array
|
||||
* The sorted array.
|
||||
*/
|
||||
protected static function recursiveKSort(array &$array) {
|
||||
// First, sort the main array.
|
||||
ksort($array);
|
||||
|
||||
// Then check for child arrays.
|
||||
foreach ($array as $key => &$value) {
|
||||
if (is_array($value)) {
|
||||
static::recursiveKSort($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a POST request for an entity, plus edge cases to ensure good DX.
|
||||
*/
|
||||
@@ -635,7 +740,7 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$response = $this->request('POST', $url, $request_options);
|
||||
$this->assertSame(415, $response->getStatusCode());
|
||||
$this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type'));
|
||||
$this->assertContains(htmlspecialchars('No "Content-Type" request header specified'), (string) $response->getBody());
|
||||
$this->assertContains('A client error happened', (string) $response->getBody());
|
||||
|
||||
|
||||
$url->setOption('query', ['_format' => static::$format]);
|
||||
@@ -741,6 +846,25 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$this->assertSame([], $response->getHeader('Location'));
|
||||
}
|
||||
$this->assertFalse($response->hasHeader('X-Drupal-Cache'));
|
||||
// Assert that the entity was indeed created, and that the response body
|
||||
// contains the serialized created entity.
|
||||
$created_entity = $this->entityStorage->loadUnchanged(static::$firstCreatedEntityId);
|
||||
$created_entity_normalization = $this->serializer->normalize($created_entity, static::$format, ['account' => $this->account]);
|
||||
// @todo Remove this if-test in https://www.drupal.org/node/2543726: execute
|
||||
// its body unconditionally.
|
||||
if (static::$entityTypeId !== 'taxonomy_term') {
|
||||
$this->assertSame($created_entity_normalization, $this->serializer->decode((string) $response->getBody(), static::$format));
|
||||
}
|
||||
// Assert that the entity was indeed created using the POSTed values.
|
||||
foreach ($this->getNormalizedPostEntity() as $field_name => $field_normalization) {
|
||||
// Some top-level keys in the normalization may not be fields on the
|
||||
// entity (for example '_links' and '_embedded' in the HAL normalization).
|
||||
if ($created_entity->hasField($field_name)) {
|
||||
// Subset, not same, because we can e.g. send just the target_id for the
|
||||
// bundle in a POST request; the response will include more properties.
|
||||
$this->assertArraySubset(static::castToString($field_normalization), $created_entity->get($field_name)->getValue(), TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$this->config('rest.settings')->set('bc_entity_resource_permissions', TRUE)->save(TRUE);
|
||||
@@ -769,6 +893,17 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$this->assertSame([], $response->getHeader('Location'));
|
||||
}
|
||||
$this->assertFalse($response->hasHeader('X-Drupal-Cache'));
|
||||
|
||||
// BC: old default POST URLs have their path updated by the inbound path
|
||||
// processor \Drupal\rest\PathProcessor\PathProcessorEntityResourceBC to the
|
||||
// new URL, which is derived from the 'create' link template if an entity
|
||||
// type specifies it.
|
||||
if ($this->entity->getEntityType()->hasLinkTemplate('create')) {
|
||||
$this->entityStorage->load(static::$secondCreatedEntityId)->delete();
|
||||
$old_url = Url::fromUri('base:entity/' . static::$entityTypeId);
|
||||
$response = $this->request('POST', $old_url, $request_options);
|
||||
$this->assertResourceResponse(201, FALSE, $response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -807,6 +942,7 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$this->assertSame(405, $response->getStatusCode());
|
||||
$this->assertSame(['GET, POST, HEAD'], $response->getHeader('Allow'));
|
||||
$this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type'));
|
||||
$this->assertContains('A client error happened', (string) $response->getBody());
|
||||
}
|
||||
else {
|
||||
$this->assertSame(404, $response->getStatusCode());
|
||||
@@ -836,7 +972,7 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$response = $this->request('PATCH', $url, $request_options);
|
||||
$this->assertSame(415, $response->getStatusCode());
|
||||
$this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type'));
|
||||
$this->assertTrue(FALSE !== strpos((string) $response->getBody(), htmlspecialchars('No "Content-Type" request header specified')));
|
||||
$this->assertContains('A client error happened', (string) $response->getBody());
|
||||
|
||||
|
||||
$url->setOption('query', ['_format' => static::$format]);
|
||||
@@ -863,7 +999,6 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$this->assertResourceErrorResponse(400, 'Syntax error', $response);
|
||||
|
||||
|
||||
|
||||
$request_options[RequestOptions::BODY] = $parseable_invalid_request_body;
|
||||
|
||||
|
||||
@@ -945,10 +1080,25 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$response = $this->request('PATCH', $url, $request_options);
|
||||
$this->assertResourceResponse(200, FALSE, $response);
|
||||
$this->assertFalse($response->hasHeader('X-Drupal-Cache'));
|
||||
// Assert that the entity was indeed updated, and that the response body
|
||||
// contains the serialized updated entity.
|
||||
$updated_entity = $this->entityStorage->loadUnchanged($this->entity->id());
|
||||
$updated_entity_normalization = $this->serializer->normalize($updated_entity, static::$format, ['account' => $this->account]);
|
||||
$this->assertSame($updated_entity_normalization, $this->serializer->decode((string) $response->getBody(), static::$format));
|
||||
// Assert that the entity was indeed created using the PATCHed values.
|
||||
foreach ($this->getNormalizedPatchEntity() as $field_name => $field_normalization) {
|
||||
// Some top-level keys in the normalization may not be fields on the
|
||||
// entity (for example '_links' and '_embedded' in the HAL normalization).
|
||||
if ($updated_entity->hasField($field_name)) {
|
||||
// Subset, not same, because we can e.g. send just the target_id for the
|
||||
// bundle in a PATCH request; the response will include more properties.
|
||||
$this->assertArraySubset(static::castToString($field_normalization), $updated_entity->get($field_name)->getValue(), TRUE);
|
||||
}
|
||||
}
|
||||
// Ensure that fields do not get deleted if they're not present in the PATCH
|
||||
// request. Test this using the configurable field that we added, but which
|
||||
// is not sent in the PATCH request.
|
||||
$this->assertSame('All the faith he had had had had no effect on the outcome of his life.', $this->entityStorage->loadUnchanged($this->entity->id())->get('field_rest_test')->value);
|
||||
$this->assertSame('All the faith he had had had had no effect on the outcome of his life.', $updated_entity->get('field_rest_test')->value);
|
||||
|
||||
|
||||
$this->config('rest.settings')->set('bc_entity_resource_permissions', TRUE)->save(TRUE);
|
||||
@@ -992,13 +1142,14 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$request_options = [];
|
||||
|
||||
|
||||
// DX: 405 when resource not provisioned, but HTML if canonical route. Plain
|
||||
// DX: 404 when resource not provisioned, but 405 if canonical route. Plain
|
||||
// text or HTML response because missing ?_format query string.
|
||||
$response = $this->request('DELETE', $url, $request_options);
|
||||
if ($has_canonical_url) {
|
||||
$this->assertSame(405, $response->getStatusCode());
|
||||
$this->assertSame(['GET, POST, HEAD'], $response->getHeader('Allow'));
|
||||
$this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type'));
|
||||
$this->assertContains('A client error happened', (string) $response->getBody());
|
||||
}
|
||||
else {
|
||||
$this->assertSame(404, $response->getStatusCode());
|
||||
@@ -1099,10 +1250,9 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
|
||||
|
||||
|
||||
// DX: 400 when incorrect entity type bundle is specified.
|
||||
// @todo Change to 422 in https://www.drupal.org/node/2827084.
|
||||
// DX: 422 when incorrect entity type bundle is specified.
|
||||
$response = $this->request($method, $url, $request_options);
|
||||
$this->assertResourceErrorResponse(400, '"bad_bundle_name" is not a valid bundle type for denormalization.', $response);
|
||||
$this->assertResourceErrorResponse(422, '"bad_bundle_name" is not a valid bundle type for denormalization.', $response);
|
||||
}
|
||||
|
||||
|
||||
@@ -1110,10 +1260,9 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
$request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
|
||||
|
||||
|
||||
// DX: 400 when no entity type bundle is specified.
|
||||
// @todo Change to 422 in https://www.drupal.org/node/2827084.
|
||||
// DX: 422 when no entity type bundle is specified.
|
||||
$response = $this->request($method, $url, $request_options);
|
||||
$this->assertResourceErrorResponse(400, sprintf('Could not determine entity type bundle: "%s" field is missing.', $bundle_field_name), $response);
|
||||
$this->assertResourceErrorResponse(422, sprintf('Could not determine entity type bundle: "%s" field is missing.', $bundle_field_name), $response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1125,7 +1274,10 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
*/
|
||||
protected function getEntityResourceUrl() {
|
||||
$has_canonical_url = $this->entity->hasLinkTemplate('canonical');
|
||||
return $has_canonical_url ? $this->entity->toUrl() : Url::fromUri('base:entity/' . static::$entityTypeId . '/' . $this->entity->id());
|
||||
// Note that the 'canonical' link relation type must be specified explicitly
|
||||
// in the call to ::toUrl(). 'canonical' is the default for
|
||||
// \Drupal\Core\Entity\Entity::toUrl(), but ConfigEntityBase overrides this.
|
||||
return $has_canonical_url ? $this->entity->toUrl('canonical') : Url::fromUri('base:entity/' . static::$entityTypeId . '/' . $this->entity->id());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1135,8 +1287,8 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
|
||||
* The URL to POST to.
|
||||
*/
|
||||
protected function getEntityResourcePostUrl() {
|
||||
$has_canonical_url = $this->entity->hasLinkTemplate('https://www.drupal.org/link-relations/create');
|
||||
return $has_canonical_url ? $this->entity->toUrl() : Url::fromUri('base:entity/' . static::$entityTypeId);
|
||||
$has_create_url = $this->entity->hasLinkTemplate('create');
|
||||
return $has_create_url ? Url::fromUri('internal:' . $this->entity->getEntityType()->getLinkTemplate('create')) : Url::fromUri('base:entity/' . static::$entityTypeId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+9
-4
@@ -3,11 +3,14 @@
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityTest;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
abstract class EntityTestResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -92,9 +95,7 @@ abstract class EntityTestResourceTestBase extends EntityResourceTestBase {
|
||||
]
|
||||
],
|
||||
'created' => [
|
||||
[
|
||||
'value' => (int) $this->entity->get('created')->value,
|
||||
]
|
||||
$this->formatExpectedTimestampItemValues((int) $this->entity->get('created')->value)
|
||||
],
|
||||
'user_id' => [
|
||||
[
|
||||
@@ -115,7 +116,11 @@ abstract class EntityTestResourceTestBase extends EntityResourceTestBase {
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return [
|
||||
'type' => 'entity_test',
|
||||
'type' => [
|
||||
[
|
||||
'value' => 'entity_test',
|
||||
],
|
||||
],
|
||||
'name' => [
|
||||
[
|
||||
'value' => 'Dramallama',
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityTestBundle;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class EntityTestBundleJsonAnonTest extends EntityTestBundleResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityTestBundle;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class EntityTestBundleJsonBasicAuthTest extends EntityTestBundleResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityTestBundle;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class EntityTestBundleJsonCookieTest extends EntityTestBundleResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityTestBundle;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTestBundle;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
abstract class EntityTestBundleResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['entity_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'entity_test_bundle';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $patchProtectedFieldNames = [];
|
||||
|
||||
/**
|
||||
* @var \Drupal\entity_test\Entity\EntityTestBundle
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer entity_test_bundle content']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$entity_test_bundle = EntityTestBundle::create([
|
||||
'id' => 'camelids',
|
||||
'label' => 'Camelids',
|
||||
'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.',
|
||||
]);
|
||||
$entity_test_bundle->save();
|
||||
|
||||
return $entity_test_bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'dependencies' => [],
|
||||
'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.',
|
||||
'id' => 'camelids',
|
||||
'label' => 'Camelids',
|
||||
'langcode' => 'en',
|
||||
'status' => TRUE,
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
}
|
||||
+9
-4
@@ -3,11 +3,14 @@
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityTestLabel;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTestLabel;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
abstract class EntityTestLabelResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -94,9 +97,7 @@ abstract class EntityTestLabelResourceTestBase extends EntityResourceTestBase {
|
||||
],
|
||||
],
|
||||
'created' => [
|
||||
[
|
||||
'value' => (int) $this->entity->get('created')->value,
|
||||
],
|
||||
$this->formatExpectedTimestampItemValues((int) $this->entity->get('created')->value),
|
||||
],
|
||||
'user_id' => [
|
||||
[
|
||||
@@ -116,7 +117,11 @@ abstract class EntityTestLabelResourceTestBase extends EntityResourceTestBase {
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return [
|
||||
'type' => 'entity_test_label',
|
||||
'type' => [
|
||||
[
|
||||
'value' => 'entity_test_label',
|
||||
],
|
||||
],
|
||||
'name' => [
|
||||
[
|
||||
'value' => 'label_llama',
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityViewMode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class EntityViewModeJsonAnonTest extends EntityViewModeResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityViewMode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class EntityViewModeJsonBasicAuthTest extends EntityViewModeResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityViewMode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class EntityViewModeJsonCookieTest extends EntityViewModeResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityViewMode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\Core\Entity\Entity\EntityViewMode;
|
||||
|
||||
abstract class EntityViewModeResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @todo: Remove 'field_ui' when https://www.drupal.org/node/2867266.
|
||||
*/
|
||||
public static $modules = ['user', 'field_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'entity_view_mode';
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Entity\EntityViewModeInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer display modes']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$entity_view_mode = EntityViewMode::create([
|
||||
'id' => 'user.test',
|
||||
'label' => 'Test',
|
||||
'targetEntityType' => 'user',
|
||||
]);
|
||||
$entity_view_mode->save();
|
||||
return $entity_view_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'cache' => TRUE,
|
||||
'dependencies' => [
|
||||
'module' => [
|
||||
'user',
|
||||
],
|
||||
],
|
||||
'id' => 'user.test',
|
||||
'label' => 'Test',
|
||||
'langcode' => 'en',
|
||||
'status' => TRUE,
|
||||
'targetEntityType' => 'user',
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,11 +2,14 @@
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Feed;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityTest\EntityTestResourceTestBase;
|
||||
use Drupal\aggregator\Entity\Feed;
|
||||
|
||||
abstract class FeedResourceTestBase extends EntityTestResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -92,14 +95,10 @@ abstract class FeedResourceTestBase extends EntityTestResourceTestBase {
|
||||
]
|
||||
],
|
||||
'checked' => [
|
||||
[
|
||||
'value' => 123456789
|
||||
]
|
||||
$this->formatExpectedTimestampItemValues(123456789),
|
||||
],
|
||||
'queued' => [
|
||||
[
|
||||
'value' => 123456789
|
||||
]
|
||||
$this->formatExpectedTimestampItemValues(123456789),
|
||||
],
|
||||
'link' => [
|
||||
[
|
||||
@@ -127,9 +126,7 @@ abstract class FeedResourceTestBase extends EntityTestResourceTestBase {
|
||||
]
|
||||
],
|
||||
'modified' => [
|
||||
[
|
||||
'value' => 123456789
|
||||
]
|
||||
$this->formatExpectedTimestampItemValues(123456789),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Drupal\Tests\rest\Functional\EntityResource\Item;
|
||||
|
||||
use Drupal\aggregator\Entity\Feed;
|
||||
use Drupal\aggregator\Entity\Item;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
/**
|
||||
@@ -11,6 +12,8 @@ use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
*/
|
||||
abstract class ItemResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -113,9 +116,7 @@ abstract class ItemResourceTestBase extends EntityResourceTestBase {
|
||||
'author' => [],
|
||||
'description' => [],
|
||||
'timestamp' => [
|
||||
[
|
||||
'value' => 123456789,
|
||||
],
|
||||
$this->formatExpectedTimestampItemValues(123456789),
|
||||
],
|
||||
'guid' => [],
|
||||
];
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Media;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class MediaJsonAnonTest extends MediaResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Media;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class MediaJsonBasicAuthTest extends MediaResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Media;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class MediaJsonCookieTest extends MediaResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
+264
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Media;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\media\Entity\Media;
|
||||
use Drupal\media\Entity\MediaType;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
abstract class MediaResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['media'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'media';
|
||||
|
||||
/**
|
||||
* @var \Drupal\media\MediaInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $patchProtectedFieldNames = [
|
||||
'changed',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$this->grantPermissionsToTestedRole(['view media']);
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
$this->grantPermissionsToTestedRole(['create media']);
|
||||
break;
|
||||
|
||||
case 'PATCH':
|
||||
$this->grantPermissionsToTestedRole(['update any media']);
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
$this->grantPermissionsToTestedRole(['delete any media']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
if (!MediaType::load('camelids')) {
|
||||
// Create a "Camelids" media type.
|
||||
$media_type = MediaType::create([
|
||||
'name' => 'Camelids',
|
||||
'id' => 'camelids',
|
||||
'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.',
|
||||
'source' => 'file',
|
||||
]);
|
||||
$media_type->save();
|
||||
// Create the source field.
|
||||
$source_field = $media_type->getSource()->createSourceField($media_type);
|
||||
$source_field->getFieldStorageDefinition()->save();
|
||||
$source_field->save();
|
||||
$media_type
|
||||
->set('source_configuration', [
|
||||
'source_field' => $source_field->getName(),
|
||||
])
|
||||
->save();
|
||||
}
|
||||
|
||||
// Create a file to upload.
|
||||
$file = File::create([
|
||||
'uri' => 'public://llama.txt',
|
||||
]);
|
||||
$file->setPermanent();
|
||||
$file->save();
|
||||
|
||||
// Create a "Llama" media item.
|
||||
$media = Media::create([
|
||||
'bundle' => 'camelids',
|
||||
'field_media_file_1' => [
|
||||
'target_id' => $file->id(),
|
||||
],
|
||||
]);
|
||||
$media
|
||||
->setName('Llama')
|
||||
->setPublished(TRUE)
|
||||
->setCreatedTime(123456789)
|
||||
->setOwnerId(static::$auth ? $this->account->id() : 0)
|
||||
->setRevisionUserId(static::$auth ? $this->account->id() : 0)
|
||||
->save();
|
||||
|
||||
return $media;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
$file = File::load(1);
|
||||
$thumbnail = File::load(2);
|
||||
$author = User::load($this->entity->getOwnerId());
|
||||
return [
|
||||
'mid' => [
|
||||
[
|
||||
'value' => 1,
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
[
|
||||
'value' => $this->entity->uuid(),
|
||||
],
|
||||
],
|
||||
'vid' => [
|
||||
[
|
||||
'value' => 1,
|
||||
],
|
||||
],
|
||||
'langcode' => [
|
||||
[
|
||||
'value' => 'en',
|
||||
],
|
||||
],
|
||||
'bundle' => [
|
||||
[
|
||||
'target_id' => 'camelids',
|
||||
'target_type' => 'media_type',
|
||||
'target_uuid' => MediaType::load('camelids')->uuid(),
|
||||
],
|
||||
],
|
||||
'name' => [
|
||||
[
|
||||
'value' => 'Llama',
|
||||
],
|
||||
],
|
||||
'field_media_file_1' => [
|
||||
[
|
||||
'description' => NULL,
|
||||
'display' => NULL,
|
||||
'target_id' => (int) $file->id(),
|
||||
'target_type' => 'file',
|
||||
'target_uuid' => $file->uuid(),
|
||||
'url' => $file->url(),
|
||||
],
|
||||
],
|
||||
'thumbnail' => [
|
||||
[
|
||||
'alt' => 'Thumbnail',
|
||||
'width' => 180,
|
||||
'height' => 180,
|
||||
'target_id' => (int) $thumbnail->id(),
|
||||
'target_type' => 'file',
|
||||
'target_uuid' => $thumbnail->uuid(),
|
||||
'title' => 'Llama',
|
||||
'url' => $thumbnail->url(),
|
||||
],
|
||||
],
|
||||
'status' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
'created' => [
|
||||
$this->formatExpectedTimestampItemValues(123456789),
|
||||
],
|
||||
'changed' => [
|
||||
$this->formatExpectedTimestampItemValues($this->entity->getChangedTime()),
|
||||
],
|
||||
'revision_created' => [
|
||||
$this->formatExpectedTimestampItemValues((int) $this->entity->getRevisionCreationTime()),
|
||||
],
|
||||
'default_langcode' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
'uid' => [
|
||||
[
|
||||
'target_id' => (int) $author->id(),
|
||||
'target_type' => 'user',
|
||||
'target_uuid' => $author->uuid(),
|
||||
'url' => base_path() . 'user/' . $author->id(),
|
||||
],
|
||||
],
|
||||
'revision_user' => [
|
||||
[
|
||||
'target_id' => (int) $author->id(),
|
||||
'target_type' => 'user',
|
||||
'target_uuid' => $author->uuid(),
|
||||
'url' => base_path() . 'user/' . $author->id(),
|
||||
],
|
||||
],
|
||||
'revision_log_message' => [],
|
||||
'revision_translation_affected' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return [
|
||||
'bundle' => [
|
||||
[
|
||||
'target_id' => 'camelids',
|
||||
],
|
||||
],
|
||||
'name' => [
|
||||
[
|
||||
'value' => 'Dramallama',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
|
||||
switch ($method) {
|
||||
case 'GET';
|
||||
return "The 'view media' permission is required and the media item must be published.";
|
||||
|
||||
case 'PATCH':
|
||||
return 'You are not authorized to update this media entity of bundle camelids.';
|
||||
|
||||
case 'DELETE':
|
||||
return 'You are not authorized to delete this media entity of bundle camelids.';
|
||||
|
||||
default:
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testPost() {
|
||||
$this->markTestSkipped('POSTing File Media items is not supported until https://www.drupal.org/node/1927648 is solved.');
|
||||
}
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\MediaType;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class MediaTypeJsonAnonTest extends MediaTypeResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\MediaType;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class MediaTypeJsonBasicAuthTest extends MediaTypeResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\MediaType;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class MediaTypeJsonCookieTest extends MediaTypeResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\MediaType;
|
||||
|
||||
use Drupal\media\Entity\MediaType;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
abstract class MediaTypeResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['media'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'media_type';
|
||||
|
||||
/**
|
||||
* @var \Drupal\media\MediaTypeInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer media types']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
// Create a "Camelids" media type.
|
||||
$camelids = MediaType::create([
|
||||
'name' => 'Camelids',
|
||||
'id' => 'camelids',
|
||||
'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.',
|
||||
'source' => 'file',
|
||||
]);
|
||||
|
||||
$camelids->save();
|
||||
|
||||
return $camelids;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'dependencies' => [],
|
||||
'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.',
|
||||
'field_map' => [],
|
||||
'id' => 'camelids',
|
||||
'label' => NULL,
|
||||
'langcode' => 'en',
|
||||
'new_revision' => FALSE,
|
||||
'queue_thumbnail_downloads' => FALSE,
|
||||
'source' => 'file',
|
||||
'source_configuration' => [
|
||||
'source_field' => '',
|
||||
],
|
||||
'status' => TRUE,
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Menu;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class MenuJsonAnonTest extends MenuResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Menu;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class MenuJsonBasicAuthTest extends MenuResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Menu;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class MenuJsonCookieTest extends MenuResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Menu;
|
||||
|
||||
use Drupal\system\Entity\Menu;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
abstract class MenuResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'menu';
|
||||
|
||||
/**
|
||||
* @var \Drupal\system\MenuInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer menu']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$menu = Menu::create([
|
||||
'id' => 'menu',
|
||||
'label' => 'Menu',
|
||||
'description' => 'Menu',
|
||||
]);
|
||||
$menu->save();
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'dependencies' => [],
|
||||
'description' => 'Menu',
|
||||
'id' => 'menu',
|
||||
'label' => 'Menu',
|
||||
'langcode' => 'en',
|
||||
'locked' => FALSE,
|
||||
'status' => TRUE,
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
return [
|
||||
'user.permissions',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
+4
-3
@@ -3,6 +3,7 @@
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\MenuLinkContent;
|
||||
|
||||
use Drupal\menu_link_content\Entity\MenuLinkContent;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
/**
|
||||
@@ -10,6 +11,8 @@ use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
*/
|
||||
abstract class MenuLinkContentResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -161,9 +164,7 @@ abstract class MenuLinkContentResourceTestBase extends EntityResourceTestBase {
|
||||
],
|
||||
],
|
||||
'changed' => [
|
||||
[
|
||||
'value' => $this->entity->getChangedTime(),
|
||||
],
|
||||
$this->formatExpectedTimestampItemValues($this->entity->getChangedTime()),
|
||||
],
|
||||
'default_langcode' => [
|
||||
[
|
||||
|
||||
+79
-13
@@ -4,15 +4,19 @@ namespace Drupal\Tests\rest\Functional\EntityResource\Node;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
|
||||
abstract class NodeResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
public static $modules = ['node', 'path'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -23,13 +27,13 @@ abstract class NodeResourceTestBase extends EntityResourceTestBase {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $patchProtectedFieldNames = [
|
||||
'uid',
|
||||
'revision_timestamp',
|
||||
'revision_uid',
|
||||
'created',
|
||||
'changed',
|
||||
'promote',
|
||||
'sticky',
|
||||
'revision_timestamp',
|
||||
'revision_uid',
|
||||
'path',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -49,6 +53,10 @@ abstract class NodeResourceTestBase extends EntityResourceTestBase {
|
||||
$this->grantPermissionsToTestedRole(['access content', 'create camelids content']);
|
||||
break;
|
||||
case 'PATCH':
|
||||
// Do not grant the 'create url aliases' permission to test the case
|
||||
// when the path field is protected/not accessible, see
|
||||
// \Drupal\Tests\rest\Functional\EntityResource\Term\TermResourceTestBase
|
||||
// for a positive test.
|
||||
$this->grantPermissionsToTestedRole(['access content', 'edit any camelids content']);
|
||||
break;
|
||||
case 'DELETE':
|
||||
@@ -77,6 +85,7 @@ abstract class NodeResourceTestBase extends EntityResourceTestBase {
|
||||
->setCreatedTime(123456789)
|
||||
->setChangedTime(123456789)
|
||||
->setRevisionCreationTime(123456789)
|
||||
->set('path', '/llama')
|
||||
->save();
|
||||
|
||||
return $node;
|
||||
@@ -120,14 +129,10 @@ abstract class NodeResourceTestBase extends EntityResourceTestBase {
|
||||
],
|
||||
],
|
||||
'created' => [
|
||||
[
|
||||
'value' => 123456789,
|
||||
],
|
||||
$this->formatExpectedTimestampItemValues(123456789),
|
||||
],
|
||||
'changed' => [
|
||||
[
|
||||
'value' => $this->entity->getChangedTime(),
|
||||
],
|
||||
$this->formatExpectedTimestampItemValues($this->entity->getChangedTime()),
|
||||
],
|
||||
'promote' => [
|
||||
[
|
||||
@@ -140,9 +145,7 @@ abstract class NodeResourceTestBase extends EntityResourceTestBase {
|
||||
],
|
||||
],
|
||||
'revision_timestamp' => [
|
||||
[
|
||||
'value' => 123456789,
|
||||
],
|
||||
$this->formatExpectedTimestampItemValues(123456789),
|
||||
],
|
||||
'revision_translation_affected' => [
|
||||
[
|
||||
@@ -171,6 +174,13 @@ abstract class NodeResourceTestBase extends EntityResourceTestBase {
|
||||
],
|
||||
],
|
||||
'revision_log' => [],
|
||||
'path' => [
|
||||
[
|
||||
'alias' => '/llama',
|
||||
'pid' => 1,
|
||||
'langcode' => 'en',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -206,4 +216,60 @@ abstract class NodeResourceTestBase extends EntityResourceTestBase {
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests PATCHing a node's path with and without 'create url aliases'.
|
||||
*
|
||||
* For a positive test, see the similar test coverage for Term.
|
||||
*
|
||||
* @see \Drupal\Tests\rest\Functional\EntityResource\Term\TermResourceTestBase::testPatchPath()
|
||||
*/
|
||||
public function testPatchPath() {
|
||||
$this->initAuthentication();
|
||||
$this->provisionEntityResource();
|
||||
$this->setUpAuthorization('GET');
|
||||
$this->setUpAuthorization('PATCH');
|
||||
|
||||
$url = $this->getEntityResourceUrl()->setOption('query', ['_format' => static::$format]);
|
||||
|
||||
// GET node's current normalization.
|
||||
$response = $this->request('GET', $url, $this->getAuthenticationRequestOptions('GET'));
|
||||
$normalization = $this->serializer->decode((string) $response->getBody(), static::$format);
|
||||
|
||||
// @todo In https://www.drupal.org/node/2824851, we will be able to stop
|
||||
// unsetting these fields from the normalization, because
|
||||
// EntityResource::patch() will ignore any fields that are sent that
|
||||
// match the current value (and obviously we're sending the current
|
||||
// value).
|
||||
$normalization = $this->removeFieldsFromNormalization($normalization, [
|
||||
'revision_timestamp',
|
||||
'revision_uid',
|
||||
'created',
|
||||
'changed',
|
||||
'promote',
|
||||
'sticky',
|
||||
]);
|
||||
|
||||
// Change node's path alias.
|
||||
$normalization['path'][0]['alias'] .= 's-rule-the-world';
|
||||
|
||||
// Create node PATCH request.
|
||||
$request_options = [];
|
||||
$request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType;
|
||||
$request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH'));
|
||||
$request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
|
||||
|
||||
// PATCH request: 403 when creating URL aliases unauthorized.
|
||||
$response = $this->request('PATCH', $url, $request_options);
|
||||
$this->assertResourceErrorResponse(403, "Access denied on updating field 'path'.", $response);
|
||||
|
||||
// Grant permission to create URL aliases.
|
||||
$this->grantPermissionsToTestedRole(['create url aliases']);
|
||||
|
||||
// Repeat PATCH request: 200.
|
||||
$response = $this->request('PATCH', $url, $request_options);
|
||||
$this->assertResourceResponse(200, FALSE, $response);
|
||||
$updated_normalization = $this->serializer->decode((string) $response->getBody(), static::$format);
|
||||
$this->assertSame($normalization['path'], $updated_normalization['path']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ResponsiveImageStyle;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ResponsiveImageStyleJsonAnonTest extends ResponsiveImageStyleResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ResponsiveImageStyle;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ResponsiveImageStyleJsonBasicAuthTest extends ResponsiveImageStyleResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ResponsiveImageStyle;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ResponsiveImageStyleJsonCookieTest extends ResponsiveImageStyleResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ResponsiveImageStyle;
|
||||
|
||||
use Drupal\responsive_image\Entity\ResponsiveImageStyle;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
/**
|
||||
* ResourceTestBase for ResponsiveImageStyle entity.
|
||||
*/
|
||||
abstract class ResponsiveImageStyleResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['responsive_image'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'responsive_image_style';
|
||||
|
||||
/**
|
||||
* The ResponsiveImageStyle entity.
|
||||
*
|
||||
* @var \Drupal\responsive_image\ResponsiveImageStyleInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* The effect UUID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $effectUuid;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer responsive images']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
// Create a "Camelids" responsive image style.
|
||||
$camelids = ResponsiveImageStyle::create([
|
||||
'id' => 'camelids',
|
||||
'label' => 'Camelids',
|
||||
]);
|
||||
$camelids->setBreakpointGroup('test_group');
|
||||
$camelids->setFallbackImageStyle('fallback');
|
||||
$camelids->addImageStyleMapping('test_breakpoint', '1x', [
|
||||
'image_mapping_type' => 'image_style',
|
||||
'image_mapping' => 'small',
|
||||
]);
|
||||
$camelids->addImageStyleMapping('test_breakpoint', '2x', [
|
||||
'image_mapping_type' => 'sizes',
|
||||
'image_mapping' => [
|
||||
'sizes' => '(min-width:700px) 700px, 100vw',
|
||||
'sizes_image_styles' => [
|
||||
'medium' => 'medium',
|
||||
'large' => 'large',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$camelids->save();
|
||||
|
||||
return $camelids;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'breakpoint_group' => 'test_group',
|
||||
'dependencies' => [
|
||||
'config' => [
|
||||
'image.style.large',
|
||||
'image.style.medium',
|
||||
],
|
||||
],
|
||||
'fallback_image_style' => 'fallback',
|
||||
'id' => 'camelids',
|
||||
'image_style_mappings' => [
|
||||
0 => [
|
||||
'breakpoint_id' => 'test_breakpoint',
|
||||
'image_mapping' => 'small',
|
||||
'image_mapping_type' => 'image_style',
|
||||
'multiplier' => '1x',
|
||||
],
|
||||
1 => [
|
||||
'breakpoint_id' => 'test_breakpoint',
|
||||
'image_mapping' => [
|
||||
'sizes' => '(min-width:700px) 700px, 100vw',
|
||||
'sizes_image_styles' => [
|
||||
'large' => 'large',
|
||||
'medium' => 'medium',
|
||||
],
|
||||
],
|
||||
'image_mapping_type' => 'sizes',
|
||||
'multiplier' => '2x',
|
||||
],
|
||||
],
|
||||
'label' => 'Camelids',
|
||||
'langcode' => 'en',
|
||||
'status' => TRUE,
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
|
||||
return "The 'administer responsive images' permission is required.";
|
||||
}
|
||||
|
||||
}
|
||||
+5
-1
@@ -132,7 +132,11 @@ abstract class ShortcutResourceTestBase extends EntityResourceTestBase {
|
||||
'uri' => 'internal:/',
|
||||
],
|
||||
],
|
||||
'shortcut_set' => 'default',
|
||||
'shortcut_set' => [
|
||||
[
|
||||
'target_id' => 'default',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
+70
-6
@@ -4,14 +4,18 @@ namespace Drupal\Tests\rest\Functional\EntityResource\Term;
|
||||
|
||||
use Drupal\taxonomy\Entity\Term;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
|
||||
abstract class TermResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['taxonomy'];
|
||||
public static $modules = ['taxonomy', 'path'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -41,8 +45,12 @@ abstract class TermResourceTestBase extends EntityResourceTestBase {
|
||||
case 'POST':
|
||||
case 'PATCH':
|
||||
case 'DELETE':
|
||||
// Grant the 'create url aliases' permission to test the case when
|
||||
// the path field is accessible, see
|
||||
// \Drupal\Tests\rest\Functional\EntityResource\Node\NodeResourceTestBase
|
||||
// for a negative test.
|
||||
// @todo Update once https://www.drupal.org/node/2824408 lands.
|
||||
$this->grantPermissionsToTestedRole(['administer taxonomy']);
|
||||
$this->grantPermissionsToTestedRole(['administer taxonomy', 'create url aliases']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -64,7 +72,8 @@ abstract class TermResourceTestBase extends EntityResourceTestBase {
|
||||
// Create a "Llama" taxonomy term.
|
||||
$term = Term::create(['vid' => $vocabulary->id()])
|
||||
->setName('Llama')
|
||||
->setChangedTime(123456789);
|
||||
->setChangedTime(123456789)
|
||||
->set('path', '/llama');
|
||||
$term->save();
|
||||
|
||||
return $term;
|
||||
@@ -107,15 +116,20 @@ abstract class TermResourceTestBase extends EntityResourceTestBase {
|
||||
],
|
||||
],
|
||||
'changed' => [
|
||||
[
|
||||
'value' => $this->entity->getChangedTime(),
|
||||
],
|
||||
$this->formatExpectedTimestampItemValues($this->entity->getChangedTime()),
|
||||
],
|
||||
'default_langcode' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
'path' => [
|
||||
[
|
||||
'alias' => '/llama',
|
||||
'pid' => 1,
|
||||
'langcode' => 'en',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -134,6 +148,12 @@ abstract class TermResourceTestBase extends EntityResourceTestBase {
|
||||
'value' => 'Dramallama',
|
||||
],
|
||||
],
|
||||
'description' => [
|
||||
[
|
||||
'value' => 'Dramallamas are the coolest camelids.',
|
||||
'format' => NULL,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -159,4 +179,48 @@ abstract class TermResourceTestBase extends EntityResourceTestBase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests PATCHing a term's path.
|
||||
*
|
||||
* For a negative test, see the similar test coverage for Node.
|
||||
*
|
||||
* @see \Drupal\Tests\rest\Functional\EntityResource\Node\NodeResourceTestBase::testPatchPath()
|
||||
*/
|
||||
public function testPatchPath() {
|
||||
$this->initAuthentication();
|
||||
$this->provisionEntityResource();
|
||||
$this->setUpAuthorization('GET');
|
||||
$this->setUpAuthorization('PATCH');
|
||||
|
||||
$url = $this->getEntityResourceUrl()->setOption('query', ['_format' => static::$format]);
|
||||
|
||||
// GET term's current normalization.
|
||||
$response = $this->request('GET', $url, $this->getAuthenticationRequestOptions('GET'));
|
||||
$normalization = $this->serializer->decode((string) $response->getBody(), static::$format);
|
||||
|
||||
// @todo In https://www.drupal.org/node/2824851, we will be able to stop
|
||||
// unsetting these fields from the normalization, because
|
||||
// EntityResource::patch() will ignore any fields that are sent that
|
||||
// match the current value (and obviously we're sending the current
|
||||
// value).
|
||||
$normalization = $this->removeFieldsFromNormalization($normalization, [
|
||||
'changed',
|
||||
]);
|
||||
|
||||
// Change term's path alias.
|
||||
$normalization['path'][0]['alias'] .= 's-rule-the-world';
|
||||
|
||||
// Create term PATCH request.
|
||||
$request_options = [];
|
||||
$request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType;
|
||||
$request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH'));
|
||||
$request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
|
||||
|
||||
// PATCH request: 200.
|
||||
$response = $this->request('PATCH', $url, $request_options);
|
||||
$this->assertResourceResponse(200, FALSE, $response);
|
||||
$updated_normalization = $this->serializer->decode((string) $response->getBody(), static::$format);
|
||||
$this->assertSame($normalization['path'], $updated_normalization['path']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Tour;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class TourJsonAnonTest extends TourResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Tour;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class TourJsonBasicAuthTest extends TourResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Tour;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class TourJsonCookieTest extends TourResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Tour;
|
||||
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\tour\Entity\Tour;
|
||||
|
||||
abstract class TourResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['tour'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'tour';
|
||||
|
||||
/**
|
||||
* @var \Drupal\tour\TourInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['access tour']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$tour = Tour::create([
|
||||
'id' => 'tour-llama',
|
||||
'label' => 'Llama tour',
|
||||
'langcode' => 'en',
|
||||
'module' => 'tour',
|
||||
'routes' => [
|
||||
[
|
||||
'route_name' => '<front>',
|
||||
],
|
||||
],
|
||||
'tips' => [
|
||||
'tour-llama-1' => [
|
||||
'id' => 'tour-llama-1',
|
||||
'plugin' => 'text',
|
||||
'label' => 'Llama',
|
||||
'body' => 'Who handle the awesomeness of llamas?',
|
||||
'weight' => 100,
|
||||
'attributes' => [
|
||||
'data-id' => 'tour-llama-1',
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$tour->save();
|
||||
|
||||
return $tour;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'dependencies' => [],
|
||||
'id' => 'tour-llama',
|
||||
'label' => 'Llama tour',
|
||||
'langcode' => 'en',
|
||||
'module' => 'tour',
|
||||
'routes' => [
|
||||
[
|
||||
'route_name' => '<front>',
|
||||
],
|
||||
],
|
||||
'status' => TRUE,
|
||||
'tips' => [
|
||||
'tour-llama-1' => [
|
||||
'id' => 'tour-llama-1',
|
||||
'plugin' => 'text',
|
||||
'label' => 'Llama',
|
||||
'body' => 'Who handle the awesomeness of llamas?',
|
||||
'weight' => 100,
|
||||
'attributes' => [
|
||||
'data-id' => 'tour-llama-1',
|
||||
],
|
||||
],
|
||||
],
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
return [
|
||||
'user.permissions',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
|
||||
return "The following permissions are required: 'access tour' OR 'administer site configuration'.";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,12 +3,15 @@
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\User;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
|
||||
abstract class UserResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -98,14 +101,10 @@ abstract class UserResourceTestBase extends EntityResourceTestBase {
|
||||
],
|
||||
],
|
||||
'created' => [
|
||||
[
|
||||
'value' => 123456789,
|
||||
],
|
||||
$this->formatExpectedTimestampItemValues(123456789),
|
||||
],
|
||||
'changed' => [
|
||||
[
|
||||
'value' => $this->entity->getChangedTime(),
|
||||
],
|
||||
$this->formatExpectedTimestampItemValues($this->entity->getChangedTime()),
|
||||
],
|
||||
'default_langcode' => [
|
||||
[
|
||||
@@ -122,7 +121,7 @@ abstract class UserResourceTestBase extends EntityResourceTestBase {
|
||||
return [
|
||||
'name' => [
|
||||
[
|
||||
'value' => 'Dramallama ' . $this->randomMachineName(),
|
||||
'value' => 'Dramallama',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\View;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ViewJsonAnonTest extends ViewResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\View;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ViewJsonBasicAuthTest extends ViewResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\View;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ViewJsonCookieTest extends ViewResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\View;
|
||||
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\views\Entity\View;
|
||||
|
||||
abstract class ViewResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['views'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'view';
|
||||
|
||||
/**
|
||||
* @var \Drupal\views\ViewEntityInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer views']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$view = View::create([
|
||||
'id' => 'test_rest',
|
||||
'label' => 'Test REST',
|
||||
]);
|
||||
$view->save();
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'base_field' => 'nid',
|
||||
'base_table' => 'node',
|
||||
'core' => '8.x',
|
||||
'dependencies' => [],
|
||||
'description' => '',
|
||||
'display' => [
|
||||
'default' => [
|
||||
'display_plugin' => 'default',
|
||||
'id' => 'default',
|
||||
'display_title' => 'Master',
|
||||
'position' => 0,
|
||||
'display_options' => [
|
||||
'display_extenders' => [],
|
||||
],
|
||||
'cache_metadata' => [
|
||||
'max-age' => -1,
|
||||
'contexts' => [
|
||||
'languages:language_interface',
|
||||
'url.query_args',
|
||||
],
|
||||
'tags' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
'id' => 'test_rest',
|
||||
'label' => 'Test REST',
|
||||
'langcode' => 'en',
|
||||
'module' => 'views',
|
||||
'status' => TRUE,
|
||||
'tag' => '',
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
return [
|
||||
'user.permissions',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional;
|
||||
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\rest\Entity\RestResourceConfig;
|
||||
use Drupal\rest\RestResourceConfigInterface;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\RoleInterface;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
|
||||
/**
|
||||
* Tests the structure of a REST resource.
|
||||
*
|
||||
* @group rest
|
||||
*/
|
||||
class ResourceTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['hal', 'rest', 'entity_test', 'rest_test'];
|
||||
|
||||
/**
|
||||
* The entity.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Create an entity programmatic.
|
||||
$this->entity = EntityTest::create([
|
||||
'name' => $this->randomMachineName(),
|
||||
'user_id' => 1,
|
||||
'field_test_text' => [
|
||||
0 => [
|
||||
'value' => $this->randomString(),
|
||||
'format' => 'plain_text',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->entity->save();
|
||||
|
||||
Role::load(AccountInterface::ANONYMOUS_ROLE)
|
||||
->grantPermission('view test entity')
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a resource without formats cannot be enabled.
|
||||
*/
|
||||
public function testFormats() {
|
||||
RestResourceConfig::create([
|
||||
'id' => 'entity.entity_test',
|
||||
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
|
||||
'configuration' => [
|
||||
'GET' => [
|
||||
'supported_auth' => [
|
||||
'basic_auth',
|
||||
],
|
||||
],
|
||||
],
|
||||
])->save();
|
||||
|
||||
// Verify that accessing the resource returns 406.
|
||||
$this->drupalGet($this->entity->urlInfo()->setRouteParameter('_format', 'hal_json'));
|
||||
// \Drupal\Core\Routing\RequestFormatRouteFilter considers the canonical,
|
||||
// non-REST route a match, but a lower quality one: no format restrictions
|
||||
// means there's always a match and hence when there is no matching REST
|
||||
// route, the non-REST route is used, but can't render into
|
||||
// application/hal+json, so it returns a 406.
|
||||
$this->assertResponse('406', 'HTTP response code is 406 when the resource does not define formats, because it falls back to the canonical, non-REST route.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a resource without authentication cannot be enabled.
|
||||
*/
|
||||
public function testAuthentication() {
|
||||
RestResourceConfig::create([
|
||||
'id' => 'entity.entity_test',
|
||||
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
|
||||
'configuration' => [
|
||||
'GET' => [
|
||||
'supported_formats' => [
|
||||
'hal_json',
|
||||
],
|
||||
],
|
||||
],
|
||||
])->save();
|
||||
|
||||
// Verify that accessing the resource returns 401.
|
||||
$this->drupalGet($this->entity->urlInfo()->setRouteParameter('_format', 'hal_json'));
|
||||
// \Drupal\Core\Routing\RequestFormatRouteFilter considers the canonical,
|
||||
// non-REST route a match, but a lower quality one: no format restrictions
|
||||
// means there's always a match and hence when there is no matching REST
|
||||
// route, the non-REST route is used, but can't render into
|
||||
// application/hal+json, so it returns a 406.
|
||||
$this->assertResponse('406', 'HTTP response code is 406 when the resource does not define formats, because it falls back to the canonical, non-REST route.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that serialization_class is optional.
|
||||
*/
|
||||
public function testSerializationClassIsOptional() {
|
||||
RestResourceConfig::create([
|
||||
'id' => 'serialization_test',
|
||||
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
|
||||
'configuration' => [
|
||||
'POST' => [
|
||||
'supported_formats' => [
|
||||
'json',
|
||||
],
|
||||
'supported_auth' => [
|
||||
'cookie',
|
||||
]
|
||||
],
|
||||
],
|
||||
])->save();
|
||||
\Drupal::service('router.builder')->rebuildIfNeeded();
|
||||
|
||||
Role::load(RoleInterface::ANONYMOUS_ID)
|
||||
->grantPermission('restful post serialization_test')
|
||||
->save();
|
||||
|
||||
$serialized = $this->container->get('serializer')->serialize(['foo', 'bar'], 'json');
|
||||
$request_options = [
|
||||
RequestOptions::HEADERS => ['Content-Type' => 'application/json'],
|
||||
RequestOptions::BODY => $serialized,
|
||||
];
|
||||
/** @var \GuzzleHttp\ClientInterface $client */
|
||||
$client = $this->getSession()->getDriver()->getClient()->getClient();
|
||||
$response = $client->request('POST', $this->buildUrl('serialization_test', ['query' => ['_format' => 'json']]), $request_options);
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
$this->assertSame('["foo","bar"]', (string) $response->getBody());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that resource URI paths are formatted properly.
|
||||
*/
|
||||
public function testUriPaths() {
|
||||
/** @var \Drupal\rest\Plugin\Type\ResourcePluginManager $manager */
|
||||
$manager = \Drupal::service('plugin.manager.rest');
|
||||
|
||||
foreach ($manager->getDefinitions() as $resource => $definition) {
|
||||
foreach ($definition['uri_paths'] as $key => $uri_path) {
|
||||
$this->assertFalse(strpos($uri_path, '//'), 'The resource URI path does not have duplicate slashes.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -62,6 +62,8 @@ abstract class ResourceTestBase extends BrowserTestBase {
|
||||
* The REST Resource plugin ID can be calculated from this.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @see \Drupal\rest\Entity\RestResourceConfig::__construct()
|
||||
*/
|
||||
protected static $resourceConfigId = NULL;
|
||||
|
||||
@@ -99,6 +101,8 @@ abstract class ResourceTestBase extends BrowserTestBase {
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->serializer = $this->container->get('serializer');
|
||||
|
||||
// Ensure the anonymous user role has no permissions at all.
|
||||
$user_role = Role::load(RoleInterface::ANONYMOUS_ID);
|
||||
foreach ($user_role->getPermissions() as $permission) {
|
||||
@@ -172,6 +176,21 @@ abstract class ResourceTestBase extends BrowserTestBase {
|
||||
\Drupal::service('router.builder')->rebuildIfNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the expected error message.
|
||||
*
|
||||
* @param string $method
|
||||
* The HTTP method (GET, POST, PATCH, DELETE).
|
||||
*
|
||||
* @return string
|
||||
* The error string.
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
$resource_plugin_id = str_replace('.', ':', static::$resourceConfigId);
|
||||
$permission = 'restful ' . strtolower($method) . ' ' . $resource_plugin_id;
|
||||
return "The '$permission' permission is required.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the necessary authorization.
|
||||
*
|
||||
@@ -230,29 +249,6 @@ abstract class ResourceTestBase extends BrowserTestBase {
|
||||
*/
|
||||
abstract protected function assertAuthenticationEdgeCases($method, Url $url, array $request_options);
|
||||
|
||||
/**
|
||||
* Return the expected error message.
|
||||
*
|
||||
* @param string $method
|
||||
* The HTTP method (GET, POST, PATCH, DELETE).
|
||||
*
|
||||
* @return string
|
||||
* The error string.
|
||||
*/
|
||||
abstract protected function getExpectedUnauthorizedAccessMessage($method);
|
||||
|
||||
/**
|
||||
* Return the default expected error message if the
|
||||
* bc_entity_resource_permissions is true.
|
||||
*
|
||||
* @param string $method
|
||||
* The HTTP method (GET, POST, PATCH, DELETE).
|
||||
*
|
||||
* @return string
|
||||
* The error string.
|
||||
*/
|
||||
abstract protected function getExpectedBcUnauthorizedAccessMessage($method);
|
||||
|
||||
/**
|
||||
* Initializes authentication.
|
||||
*
|
||||
@@ -321,6 +317,9 @@ abstract class ResourceTestBase extends BrowserTestBase {
|
||||
* 'http_errors = FALSE' request option, nor do we want them to have to
|
||||
* convert Drupal Url objects to strings.
|
||||
*
|
||||
* We also don't want to follow redirects automatically, to ensure these tests
|
||||
* are able to detect when redirects are added or removed.
|
||||
*
|
||||
* @see \GuzzleHttp\ClientInterface::request()
|
||||
*
|
||||
* @param string $method
|
||||
@@ -334,6 +333,7 @@ abstract class ResourceTestBase extends BrowserTestBase {
|
||||
*/
|
||||
protected function request($method, Url $url, array $request_options) {
|
||||
$request_options[RequestOptions::HTTP_ERRORS] = FALSE;
|
||||
$request_options[RequestOptions::ALLOW_REDIRECTS] = FALSE;
|
||||
$request_options = $this->decorateWithXdebugCookie($request_options);
|
||||
$client = $this->getSession()->getDriver()->getClient()->getClient();
|
||||
return $client->request($method, $url->setAbsolute(TRUE)->toString(), $request_options);
|
||||
@@ -351,12 +351,7 @@ abstract class ResourceTestBase extends BrowserTestBase {
|
||||
*/
|
||||
protected function assertResourceResponse($expected_status_code, $expected_body, ResponseInterface $response) {
|
||||
$this->assertSame($expected_status_code, $response->getStatusCode());
|
||||
if ($expected_status_code < 400) {
|
||||
$this->assertSame([static::$mimeType], $response->getHeader('Content-Type'));
|
||||
}
|
||||
else {
|
||||
$this->assertSame([static::$mimeType], $response->getHeader('Content-Type'));
|
||||
}
|
||||
$this->assertSame([static::$mimeType], $response->getHeader('Content-Type'));
|
||||
if ($expected_body !== FALSE) {
|
||||
$this->assertSame($expected_body, (string) $response->getBody());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Update;
|
||||
|
||||
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests that existing sites continue to use permissions for EntityResource.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2664780
|
||||
*
|
||||
* @group rest
|
||||
*/
|
||||
class EntityResourcePermissionsUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['rest', 'serialization'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
__DIR__ . '/../../../fixtures/update/drupal-8.rest-rest_update_8203.php',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rest_update_8203().
|
||||
*/
|
||||
public function testBcEntityResourcePermissionSettingAdded() {
|
||||
$permission_handler = $this->container->get('user.permissions');
|
||||
|
||||
$is_rest_resource_permission = function ($permission) {
|
||||
return $permission['provider'] === 'rest' && (string) $permission['title'] !== 'Administer REST resource configuration';
|
||||
};
|
||||
|
||||
// Make sure we have the expected values before the update.
|
||||
$rest_settings = $this->config('rest.settings');
|
||||
$this->assertFalse(array_key_exists('bc_entity_resource_permissions', $rest_settings->getRawData()));
|
||||
$this->assertEqual([], array_filter($permission_handler->getPermissions(), $is_rest_resource_permission));
|
||||
|
||||
$this->runUpdates();
|
||||
|
||||
// Make sure we have the expected values after the update.
|
||||
$rest_settings = $this->config('rest.settings');
|
||||
$this->assertTrue(array_key_exists('bc_entity_resource_permissions', $rest_settings->getRawData()));
|
||||
$this->assertTrue($rest_settings->get('bc_entity_resource_permissions'));
|
||||
$rest_permissions = array_keys(array_filter($permission_handler->getPermissions(), $is_rest_resource_permission));
|
||||
$this->assertEqual(['restful delete entity:node', 'restful get entity:node', 'restful patch entity:node', 'restful post entity:node'], $rest_permissions);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Update;
|
||||
|
||||
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests method-granularity REST config is simplified to resource-granularity.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2721595
|
||||
* @see rest_post_update_resource_granularity()
|
||||
*
|
||||
* @group rest
|
||||
*/
|
||||
class ResourceGranularityUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['rest', 'serialization'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
__DIR__ . '/../../../fixtures/update/drupal-8.rest-rest_post_update_resource_granularity.php',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rest_post_update_simplify_resource_granularity().
|
||||
*/
|
||||
public function testMethodGranularityConvertedToResourceGranularity() {
|
||||
/** @var \Drupal\Core\Entity\EntityStorageInterface $resource_config_storage */
|
||||
$resource_config_storage = $this->container->get('entity_type.manager')->getStorage('rest_resource_config');
|
||||
|
||||
// Make sure we have the expected values before the update.
|
||||
$resource_config_entities = $resource_config_storage->loadMultiple();
|
||||
$this->assertIdentical(['entity.comment', 'entity.node', 'entity.user'], array_keys($resource_config_entities));
|
||||
$this->assertIdentical('method', $resource_config_entities['entity.node']->get('granularity'));
|
||||
$this->assertIdentical('method', $resource_config_entities['entity.comment']->get('granularity'));
|
||||
$this->assertIdentical('method', $resource_config_entities['entity.user']->get('granularity'));
|
||||
|
||||
// Read the existing 'entity:comment' and 'entity:user' resource
|
||||
// configuration so we can verify it after the update.
|
||||
$comment_resource_configuration = $resource_config_entities['entity.comment']->get('configuration');
|
||||
$user_resource_configuration = $resource_config_entities['entity.user']->get('configuration');
|
||||
|
||||
$this->runUpdates();
|
||||
|
||||
// Make sure we have the expected values after the update.
|
||||
$resource_config_entities = $resource_config_storage->loadMultiple();
|
||||
$this->assertIdentical(['entity.comment', 'entity.node', 'entity.user'], array_keys($resource_config_entities));
|
||||
// 'entity:node' should be updated.
|
||||
$this->assertIdentical('resource', $resource_config_entities['entity.node']->get('granularity'));
|
||||
$this->assertidentical($resource_config_entities['entity.node']->get('configuration'), [
|
||||
'methods' => ['GET', 'POST', 'PATCH', 'DELETE'],
|
||||
'formats' => ['hal_json'],
|
||||
'authentication' => ['basic_auth'],
|
||||
]);
|
||||
// 'entity:comment' should be unchanged.
|
||||
$this->assertIdentical('method', $resource_config_entities['entity.comment']->get('granularity'));
|
||||
$this->assertIdentical($comment_resource_configuration, $resource_config_entities['entity.comment']->get('configuration'));
|
||||
// 'entity:user' should be unchanged.
|
||||
$this->assertIdentical('method', $resource_config_entities['entity.user']->get('granularity'));
|
||||
$this->assertIdentical($user_resource_configuration, $resource_config_entities['entity.user']->get('configuration'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Update;
|
||||
|
||||
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
use Drupal\rest\RestResourceConfigInterface;
|
||||
|
||||
/**
|
||||
* Tests that rest.settings is converted to rest_resource_config entities.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2308745
|
||||
* @see rest_update_8201()
|
||||
* @see rest_post_update_create_rest_resource_config_entities()
|
||||
*
|
||||
* @group rest
|
||||
*/
|
||||
class RestConfigurationEntitiesUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['rest', 'serialization'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
__DIR__ . '/../../../fixtures/update/drupal-8.rest-rest_update_8201.php',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rest_update_8201().
|
||||
*/
|
||||
public function testResourcesConvertedToConfigEntities() {
|
||||
/** @var \Drupal\Core\Entity\EntityStorageInterface $resource_config_storage */
|
||||
$resource_config_storage = $this->container->get('entity_type.manager')->getStorage('rest_resource_config');
|
||||
|
||||
// Make sure we have the expected values before the update.
|
||||
$rest_settings = $this->config('rest.settings');
|
||||
$this->assertTrue(array_key_exists('resources', $rest_settings->getRawData()));
|
||||
$this->assertTrue(array_key_exists('entity:node', $rest_settings->getRawData()['resources']));
|
||||
$resource_config_entities = $resource_config_storage->loadMultiple();
|
||||
$this->assertIdentical([], array_keys($resource_config_entities));
|
||||
|
||||
$this->runUpdates();
|
||||
|
||||
// Make sure we have the expected values after the update.
|
||||
$rest_settings = $this->config('rest.settings');
|
||||
$this->assertFalse(array_key_exists('resources', $rest_settings->getRawData()));
|
||||
$resource_config_entities = $resource_config_storage->loadMultiple();
|
||||
$this->assertIdentical(['entity.node'], array_keys($resource_config_entities));
|
||||
$node_resource_config_entity = $resource_config_entities['entity.node'];
|
||||
$this->assertIdentical(RestResourceConfigInterface::RESOURCE_GRANULARITY, $node_resource_config_entity->get('granularity'));
|
||||
$this->assertIdentical([
|
||||
'methods' => ['GET'],
|
||||
'formats' => ['json'],
|
||||
'authentication' => ['basic_auth'],
|
||||
], $node_resource_config_entity->get('configuration'));
|
||||
$this->assertIdentical(['module' => ['basic_auth', 'node', 'serialization']], $node_resource_config_entity->getDependencies());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Update;
|
||||
|
||||
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Ensures that update hook is run properly for REST Export config.
|
||||
*
|
||||
* @group Update
|
||||
*/
|
||||
class RestExportAuthUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
__DIR__ . '/../../../../tests/fixtures/update/rest-export-with-authentication.php',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that update hook is run for rest module.
|
||||
*/
|
||||
public function testUpdate() {
|
||||
$this->runUpdates();
|
||||
|
||||
// Get particular view.
|
||||
$view = \Drupal::entityTypeManager()->getStorage('view')->load('rest_export_with_authorization');
|
||||
$displays = $view->get('display');
|
||||
$this->assertIdentical($displays['rest_export_1']['display_options']['auth']['basic_auth'], 'basic_auth', 'Basic authentication is set as authentication method.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Views;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the display of an excluded field that is used as a token.
|
||||
*
|
||||
* @group rest
|
||||
* @see \Drupal\rest\Plugin\views\display\RestExport
|
||||
* @see \Drupal\rest\Plugin\views\row\DataFieldRow
|
||||
*/
|
||||
class ExcludedFieldTokenTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\views\ViewExecutable
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* The views that are used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_excluded_field_token_display'];
|
||||
|
||||
/**
|
||||
* The modules that need to be installed for this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'entity_test',
|
||||
'rest_test_views',
|
||||
'node',
|
||||
'field',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['rest_test_views']);
|
||||
|
||||
// Create some test content.
|
||||
for ($i = 1; $i <= 10; $i++) {
|
||||
Node::create([
|
||||
'type' => 'article',
|
||||
'title' => 'Article test ' . $i,
|
||||
])->save();
|
||||
}
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
|
||||
$this->view = Views::getView('test_excluded_field_token_display');
|
||||
$this->view->setDisplay('rest_export_1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the display of an excluded title field when used as a token.
|
||||
*/
|
||||
public function testExcludedTitleTokenDisplay() {
|
||||
$actual_json = $this->drupalGet($this->view->getPath(), ['query' => ['_format' => 'json']]);
|
||||
$this->assertResponse(200);
|
||||
|
||||
$expected = [
|
||||
['nothing' => 'Article test 10'],
|
||||
['nothing' => 'Article test 9'],
|
||||
['nothing' => 'Article test 8'],
|
||||
['nothing' => 'Article test 7'],
|
||||
['nothing' => 'Article test 6'],
|
||||
['nothing' => 'Article test 5'],
|
||||
['nothing' => 'Article test 4'],
|
||||
['nothing' => 'Article test 3'],
|
||||
['nothing' => 'Article test 2'],
|
||||
['nothing' => 'Article test 1'],
|
||||
];
|
||||
$this->assertIdentical($actual_json, json_encode($expected));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Views;
|
||||
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Entity\View;
|
||||
|
||||
/**
|
||||
* Tests authentication for REST display.
|
||||
*
|
||||
* @group rest
|
||||
*/
|
||||
class RestExportAuthTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['rest', 'views_ui', 'basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer views']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that correct authentication providers are available for choosing.
|
||||
*
|
||||
* @link https://www.drupal.org/node/2825204
|
||||
*/
|
||||
public function testAuthProvidersOptions() {
|
||||
$view_id = 'test_view_rest_export';
|
||||
$view_label = 'Test view (REST export)';
|
||||
$view_display = 'rest_export_1';
|
||||
$view_rest_path = 'test-view/rest-export';
|
||||
|
||||
// Create new view.
|
||||
$this->drupalPostForm('admin/structure/views/add', [
|
||||
'id' => $view_id,
|
||||
'label' => $view_label,
|
||||
'show[wizard_key]' => 'users',
|
||||
'rest_export[path]' => $view_rest_path,
|
||||
'rest_export[create]' => TRUE,
|
||||
], t('Save and edit'));
|
||||
|
||||
$this->drupalGet("admin/structure/views/nojs/display/$view_id/$view_display/auth");
|
||||
// The "basic_auth" will always be available since module,
|
||||
// providing it, has the same name.
|
||||
$this->assertField('edit-auth-basic-auth', 'Basic auth is available for choosing.');
|
||||
// The "cookie" authentication provider defined by "user" module.
|
||||
$this->assertField('edit-auth-cookie', 'Cookie-based auth can be chosen.');
|
||||
// Wrong behavior in "getAuthOptions()" method makes this option available
|
||||
// instead of "cookie".
|
||||
// @see \Drupal\rest\Plugin\views\display\RestExport::getAuthOptions()
|
||||
$this->assertNoField('edit-auth-user', 'Wrong authentication option is unavailable.');
|
||||
|
||||
$this->drupalPostForm(NULL, ['auth[basic_auth]' => 1, 'auth[cookie]' => 1], 'Apply');
|
||||
$this->drupalPostForm(NULL, [], 'Save');
|
||||
|
||||
$view = View::load($view_id);
|
||||
$this->assertEquals(['basic_auth', 'cookie'], $view->getDisplay('rest_export_1')['display_options']['auth']);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,832 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Views;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Entity\View;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Tests the serializer style plugin.
|
||||
*
|
||||
* @group rest
|
||||
* @see \Drupal\rest\Plugin\views\display\RestExport
|
||||
* @see \Drupal\rest\Plugin\views\style\Serializer
|
||||
* @see \Drupal\rest\Plugin\views\row\DataEntityRow
|
||||
* @see \Drupal\rest\Plugin\views\row\DataFieldRow
|
||||
*/
|
||||
class StyleSerializerTest extends ViewTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['views_ui', 'entity_test', 'hal', 'rest_test_views', 'node', 'text', 'field', 'language', 'basic_auth'];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_serializer_display_field', 'test_serializer_display_entity', 'test_serializer_display_entity_translated', 'test_serializer_node_display_field', 'test_serializer_node_exposed_filter'];
|
||||
|
||||
/**
|
||||
* A user with administrative privileges to look at test entity and configure views.
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['rest_test_views']);
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser(['administer views', 'administer entity_test content', 'access user profiles', 'view test entity']);
|
||||
|
||||
// Save some entity_test entities.
|
||||
for ($i = 1; $i <= 10; $i++) {
|
||||
EntityTest::create(['name' => 'test_' . $i, 'user_id' => $this->adminUser->id()])->save();
|
||||
}
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the auth options restricts access to a REST views display.
|
||||
*/
|
||||
public function testRestViewsAuthentication() {
|
||||
// Assume the view is hidden behind a permission.
|
||||
$this->drupalGet('test/serialize/auth_with_perm', ['query' => ['_format' => 'json']]);
|
||||
$this->assertResponse(401);
|
||||
|
||||
// Not even logging in would make it possible to see the view, because then
|
||||
// we are denied based on authentication method (cookie).
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('test/serialize/auth_with_perm', ['query' => ['_format' => 'json']]);
|
||||
$this->assertResponse(403);
|
||||
$this->drupalLogout();
|
||||
|
||||
// But if we use the basic auth authentication strategy, we should be able
|
||||
// to see the page.
|
||||
$url = $this->buildUrl('test/serialize/auth_with_perm');
|
||||
$response = \Drupal::httpClient()->get($url, [
|
||||
'auth' => [$this->adminUser->getUsername(), $this->adminUser->pass_raw],
|
||||
]);
|
||||
|
||||
// Ensure that any changes to variables in the other thread are picked up.
|
||||
$this->refreshVariables();
|
||||
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the behavior of the Serializer callback paths and row plugins.
|
||||
*/
|
||||
public function testSerializerResponses() {
|
||||
// Test the serialize callback.
|
||||
$view = Views::getView('test_serializer_display_field');
|
||||
$view->initDisplay();
|
||||
$this->executeView($view);
|
||||
|
||||
$actual_json = $this->drupalGet('test/serialize/field', ['query' => ['_format' => 'json']]);
|
||||
$this->assertResponse(200);
|
||||
$this->assertCacheTags($view->getCacheTags());
|
||||
$this->assertCacheContexts(['languages:language_interface', 'theme', 'request_format']);
|
||||
// @todo Due to https://www.drupal.org/node/2352009 we can't yet test the
|
||||
// propagation of cache max-age.
|
||||
|
||||
// Test the http Content-type.
|
||||
$headers = $this->drupalGetHeaders();
|
||||
$this->assertSame(['application/json'], $headers['Content-Type']);
|
||||
|
||||
$expected = [];
|
||||
foreach ($view->result as $row) {
|
||||
$expected_row = [];
|
||||
foreach ($view->field as $id => $field) {
|
||||
$expected_row[$id] = $field->render($row);
|
||||
}
|
||||
$expected[] = $expected_row;
|
||||
}
|
||||
|
||||
$this->assertIdentical($actual_json, json_encode($expected), 'The expected JSON output was found.');
|
||||
|
||||
|
||||
// Test that the rendered output and the preview output are the same.
|
||||
$view->destroy();
|
||||
$view->setDisplay('rest_export_1');
|
||||
// Mock the request content type by setting it on the display handler.
|
||||
$view->display_handler->setContentType('json');
|
||||
$output = $view->preview();
|
||||
$this->assertIdentical($actual_json, (string) drupal_render_root($output), 'The expected JSON preview output was found.');
|
||||
|
||||
// Test a 403 callback.
|
||||
$this->drupalGet('test/serialize/denied');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test the entity rows.
|
||||
$view = Views::getView('test_serializer_display_entity');
|
||||
$view->initDisplay();
|
||||
$this->executeView($view);
|
||||
|
||||
// Get the serializer service.
|
||||
$serializer = $this->container->get('serializer');
|
||||
|
||||
$entities = [];
|
||||
foreach ($view->result as $row) {
|
||||
$entities[] = $row->_entity;
|
||||
}
|
||||
|
||||
$expected = $serializer->serialize($entities, 'json');
|
||||
|
||||
$actual_json = $this->drupalGet('test/serialize/entity', ['query' => ['_format' => 'json']]);
|
||||
$this->assertResponse(200);
|
||||
$this->assertIdentical($actual_json, $expected, 'The expected JSON output was found.');
|
||||
$expected_cache_tags = $view->getCacheTags();
|
||||
$expected_cache_tags[] = 'entity_test_list';
|
||||
/** @var \Drupal\Core\Entity\EntityInterface $entity */
|
||||
foreach ($entities as $entity) {
|
||||
$expected_cache_tags = Cache::mergeTags($expected_cache_tags, $entity->getCacheTags());
|
||||
}
|
||||
$this->assertCacheTags($expected_cache_tags);
|
||||
$this->assertCacheContexts(['languages:language_interface', 'theme', 'entity_test_view_grants', 'request_format']);
|
||||
|
||||
$expected = $serializer->serialize($entities, 'hal_json');
|
||||
$actual_json = $this->drupalGet('test/serialize/entity', ['query' => ['_format' => 'hal_json']]);
|
||||
$this->assertIdentical($actual_json, $expected, 'The expected HAL output was found.');
|
||||
$this->assertCacheTags($expected_cache_tags);
|
||||
|
||||
// Change the default format to xml.
|
||||
$view->setDisplay('rest_export_1');
|
||||
$view->getDisplay()->setOption('style', [
|
||||
'type' => 'serializer',
|
||||
'options' => [
|
||||
'uses_fields' => FALSE,
|
||||
'formats' => [
|
||||
'xml' => 'xml',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$view->save();
|
||||
$expected = $serializer->serialize($entities, 'xml');
|
||||
$actual_xml = $this->drupalGet('test/serialize/entity', ['query' => ['_format' => 'xml']]);
|
||||
$this->assertSame(trim($expected), $actual_xml);
|
||||
$this->assertCacheContexts(['languages:language_interface', 'theme', 'entity_test_view_grants', 'request_format']);
|
||||
|
||||
// Allow multiple formats.
|
||||
$view->setDisplay('rest_export_1');
|
||||
$view->getDisplay()->setOption('style', [
|
||||
'type' => 'serializer',
|
||||
'options' => [
|
||||
'uses_fields' => FALSE,
|
||||
'formats' => [
|
||||
'xml' => 'xml',
|
||||
'json' => 'json',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$view->save();
|
||||
$expected = $serializer->serialize($entities, 'json');
|
||||
$actual_json = $this->drupalGet('test/serialize/entity', ['query' => ['_format' => 'json']]);
|
||||
$this->assertIdentical($actual_json, $expected, 'The expected JSON output was found.');
|
||||
$expected = $serializer->serialize($entities, 'xml');
|
||||
$actual_xml = $this->drupalGet('test/serialize/entity', ['query' => ['_format' => 'xml']]);
|
||||
$this->assertSame(trim($expected), $actual_xml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies site maintenance mode functionality.
|
||||
*/
|
||||
public function testSiteMaintenance() {
|
||||
$view = Views::getView('test_serializer_display_field');
|
||||
$view->initDisplay();
|
||||
$this->executeView($view);
|
||||
|
||||
// Set the site to maintenance mode.
|
||||
$this->container->get('state')->set('system.maintenance_mode', TRUE);
|
||||
|
||||
$this->drupalGet('test/serialize/entity', ['query' => ['_format' => 'json']]);
|
||||
// Verify that the endpoint is unavailable for anonymous users.
|
||||
$this->assertResponse(503);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a request on the request stack with a specified format.
|
||||
*
|
||||
* @param string $format
|
||||
* The new request format.
|
||||
*/
|
||||
protected function addRequestWithFormat($format) {
|
||||
$request = \Drupal::request();
|
||||
$request = clone $request;
|
||||
$request->setRequestFormat($format);
|
||||
|
||||
\Drupal::requestStack()->push($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests REST export with views render caching enabled.
|
||||
*/
|
||||
public function testRestRenderCaching() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
/** @var \Drupal\Core\Render\RenderCacheInterface $render_cache */
|
||||
$render_cache = \Drupal::service('render_cache');
|
||||
|
||||
// Enable render caching for the views.
|
||||
/** @var \Drupal\views\ViewEntityInterface $storage */
|
||||
$storage = View::load('test_serializer_display_entity');
|
||||
$options = &$storage->getDisplay('default');
|
||||
$options['display_options']['cache'] = [
|
||||
'type' => 'tag',
|
||||
];
|
||||
$storage->save();
|
||||
|
||||
$original = DisplayPluginBase::buildBasicRenderable('test_serializer_display_entity', 'rest_export_1');
|
||||
|
||||
// Ensure that there is no corresponding render cache item yet.
|
||||
$original['#cache'] += ['contexts' => []];
|
||||
$original['#cache']['contexts'] = Cache::mergeContexts($original['#cache']['contexts'], $this->container->getParameter('renderer.config')['required_cache_contexts']);
|
||||
|
||||
$cache_tags = [
|
||||
'config:views.view.test_serializer_display_entity',
|
||||
'entity_test:1',
|
||||
'entity_test:10',
|
||||
'entity_test:2',
|
||||
'entity_test:3',
|
||||
'entity_test:4',
|
||||
'entity_test:5',
|
||||
'entity_test:6',
|
||||
'entity_test:7',
|
||||
'entity_test:8',
|
||||
'entity_test:9',
|
||||
'entity_test_list'
|
||||
];
|
||||
$cache_contexts = [
|
||||
'entity_test_view_grants',
|
||||
'languages:language_interface',
|
||||
'theme',
|
||||
'request_format',
|
||||
];
|
||||
|
||||
$this->assertFalse($render_cache->get($original));
|
||||
|
||||
// Request the page, once in XML and once in JSON to ensure that the caching
|
||||
// varies by it.
|
||||
$result1 = Json::decode($this->drupalGet('test/serialize/entity', ['query' => ['_format' => 'json']]));
|
||||
$this->addRequestWithFormat('json');
|
||||
$this->assertHeader('content-type', 'application/json');
|
||||
$this->assertCacheContexts($cache_contexts);
|
||||
$this->assertCacheTags($cache_tags);
|
||||
$this->assertTrue($render_cache->get($original));
|
||||
|
||||
$result_xml = $this->drupalGet('test/serialize/entity', ['query' => ['_format' => 'xml']]);
|
||||
$this->addRequestWithFormat('xml');
|
||||
$this->assertHeader('content-type', 'text/xml; charset=UTF-8');
|
||||
$this->assertCacheContexts($cache_contexts);
|
||||
$this->assertCacheTags($cache_tags);
|
||||
$this->assertTrue($render_cache->get($original));
|
||||
|
||||
// Ensure that the XML output is different from the JSON one.
|
||||
$this->assertNotEqual($result1, $result_xml);
|
||||
|
||||
// Ensure that the cached page works.
|
||||
$result2 = Json::decode($this->drupalGet('test/serialize/entity', ['query' => ['_format' => 'json']]));
|
||||
$this->addRequestWithFormat('json');
|
||||
$this->assertHeader('content-type', 'application/json');
|
||||
$this->assertEqual($result2, $result1);
|
||||
$this->assertCacheContexts($cache_contexts);
|
||||
$this->assertCacheTags($cache_tags);
|
||||
$this->assertTrue($render_cache->get($original));
|
||||
|
||||
// Create a new entity and ensure that the cache tags are taken over.
|
||||
EntityTest::create(['name' => 'test_11', 'user_id' => $this->adminUser->id()])->save();
|
||||
$result3 = Json::decode($this->drupalGet('test/serialize/entity', ['query' => ['_format' => 'json']]));
|
||||
$this->addRequestWithFormat('json');
|
||||
$this->assertHeader('content-type', 'application/json');
|
||||
$this->assertNotEqual($result3, $result2);
|
||||
|
||||
// Add the new entity cache tag and remove the first one, because we just
|
||||
// show 10 items in total.
|
||||
$cache_tags[] = 'entity_test:11';
|
||||
unset($cache_tags[array_search('entity_test:1', $cache_tags)]);
|
||||
|
||||
$this->assertCacheContexts($cache_contexts);
|
||||
$this->assertCacheTags($cache_tags);
|
||||
$this->assertTrue($render_cache->get($original));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the response format configuration.
|
||||
*/
|
||||
public function testResponseFormatConfiguration() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
$style_options = 'admin/structure/views/nojs/display/test_serializer_display_field/rest_export_1/style_options';
|
||||
|
||||
// Select only 'xml' as an accepted format.
|
||||
$this->drupalPostForm($style_options, ['style_options[formats][xml]' => 'xml'], t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
// Should return a 406.
|
||||
$this->drupalGet('test/serialize/field', ['query' => ['_format' => 'json']]);
|
||||
$this->assertHeader('content-type', 'application/json');
|
||||
$this->assertResponse(406, 'A 406 response was returned when JSON was requested.');
|
||||
// Should return a 200.
|
||||
$this->drupalGet('test/serialize/field', ['query' => ['_format' => 'xml']]);
|
||||
$this->assertHeader('content-type', 'text/xml; charset=UTF-8');
|
||||
$this->assertResponse(200, 'A 200 response was returned when XML was requested.');
|
||||
|
||||
// Add 'json' as an accepted format, so we have multiple.
|
||||
$this->drupalPostForm($style_options, ['style_options[formats][json]' => 'json'], t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
// Should return a 200.
|
||||
// @todo This should be fixed when we have better content negotiation.
|
||||
$this->drupalGet('test/serialize/field');
|
||||
$this->assertHeader('content-type', 'application/json');
|
||||
$this->assertResponse(200, 'A 200 response was returned when any format was requested.');
|
||||
|
||||
// Should return a 200. Emulates a sample Firefox header.
|
||||
$this->drupalGet('test/serialize/field', [], ['Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8']);
|
||||
$this->assertHeader('content-type', 'application/json');
|
||||
$this->assertResponse(200, 'A 200 response was returned when a browser accept header was requested.');
|
||||
|
||||
// Should return a 200.
|
||||
$this->drupalGet('test/serialize/field', ['query' => ['_format' => 'json']]);
|
||||
$this->assertHeader('content-type', 'application/json');
|
||||
$this->assertResponse(200, 'A 200 response was returned when JSON was requested.');
|
||||
$headers = $this->drupalGetHeaders();
|
||||
$this->assertEqual($headers['Content-Type'], ['application/json'], 'The header Content-type is correct.');
|
||||
// Should return a 200.
|
||||
$this->drupalGet('test/serialize/field', ['query' => ['_format' => 'xml']]);
|
||||
$this->assertHeader('content-type', 'text/xml; charset=UTF-8');
|
||||
$this->assertResponse(200, 'A 200 response was returned when XML was requested');
|
||||
$headers = $this->drupalGetHeaders();
|
||||
$this->assertSame(['text/xml; charset=UTF-8'], $headers['Content-Type']);
|
||||
// Should return a 406.
|
||||
$this->drupalGet('test/serialize/field', ['query' => ['_format' => 'html']]);
|
||||
// We want to show the first format by default, see
|
||||
// \Drupal\rest\Plugin\views\style\Serializer::render.
|
||||
$this->assertHeader('content-type', 'application/json');
|
||||
$this->assertResponse(200, 'A 200 response was returned when HTML was requested.');
|
||||
|
||||
// Now configure now format, so all of them should be allowed.
|
||||
$this->drupalPostForm($style_options, ['style_options[formats][json]' => '0', 'style_options[formats][xml]' => '0'], t('Apply'));
|
||||
|
||||
// Should return a 200.
|
||||
$this->drupalGet('test/serialize/field', ['query' => ['_format' => 'json']]);
|
||||
$this->assertHeader('content-type', 'application/json');
|
||||
$this->assertResponse(200, 'A 200 response was returned when JSON was requested.');
|
||||
// Should return a 200.
|
||||
$this->drupalGet('test/serialize/field', ['query' => ['_format' => 'xml']]);
|
||||
$this->assertHeader('content-type', 'text/xml; charset=UTF-8');
|
||||
$this->assertResponse(200, 'A 200 response was returned when XML was requested');
|
||||
// Should return a 200.
|
||||
$this->drupalGet('test/serialize/field', ['query' => ['_format' => 'html']]);
|
||||
// We want to show the first format by default, see
|
||||
// \Drupal\rest\Plugin\views\style\Serializer::render.
|
||||
$this->assertHeader('content-type', 'application/json');
|
||||
$this->assertResponse(200, 'A 200 response was returned when HTML was requested.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the field ID alias functionality of the DataFieldRow plugin.
|
||||
*/
|
||||
public function testUIFieldAlias() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Test the UI settings for adding field ID aliases.
|
||||
$this->drupalGet('admin/structure/views/view/test_serializer_display_field/edit/rest_export_1');
|
||||
$row_options = 'admin/structure/views/nojs/display/test_serializer_display_field/rest_export_1/row_options';
|
||||
$this->assertLinkByHref($row_options);
|
||||
|
||||
// Test an empty string for an alias, this should not be used. This also
|
||||
// tests that the form can be submitted with no aliases.
|
||||
$this->drupalPostForm($row_options, ['row_options[field_options][name][alias]' => ''], t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
$view = Views::getView('test_serializer_display_field');
|
||||
$view->setDisplay('rest_export_1');
|
||||
$this->executeView($view);
|
||||
|
||||
$expected = [];
|
||||
foreach ($view->result as $row) {
|
||||
$expected_row = [];
|
||||
foreach ($view->field as $id => $field) {
|
||||
$expected_row[$id] = $field->render($row);
|
||||
}
|
||||
$expected[] = $expected_row;
|
||||
}
|
||||
|
||||
$this->assertIdentical(Json::decode($this->drupalGet('test/serialize/field', ['query' => ['_format' => 'json']])), $this->castSafeStrings($expected));
|
||||
|
||||
// Test a random aliases for fields, they should be replaced.
|
||||
$alias_map = [
|
||||
'name' => $this->randomMachineName(),
|
||||
// Use # to produce an invalid character for the validation.
|
||||
'nothing' => '#' . $this->randomMachineName(),
|
||||
'created' => 'created',
|
||||
];
|
||||
|
||||
$edit = ['row_options[field_options][name][alias]' => $alias_map['name'], 'row_options[field_options][nothing][alias]' => $alias_map['nothing']];
|
||||
$this->drupalPostForm($row_options, $edit, t('Apply'));
|
||||
$this->assertText(t('The machine-readable name must contain only letters, numbers, dashes and underscores.'));
|
||||
|
||||
// Change the map alias value to a valid one.
|
||||
$alias_map['nothing'] = $this->randomMachineName();
|
||||
|
||||
$edit = ['row_options[field_options][name][alias]' => $alias_map['name'], 'row_options[field_options][nothing][alias]' => $alias_map['nothing']];
|
||||
$this->drupalPostForm($row_options, $edit, t('Apply'));
|
||||
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
$view = Views::getView('test_serializer_display_field');
|
||||
$view->setDisplay('rest_export_1');
|
||||
$this->executeView($view);
|
||||
|
||||
$expected = [];
|
||||
foreach ($view->result as $row) {
|
||||
$expected_row = [];
|
||||
foreach ($view->field as $id => $field) {
|
||||
$expected_row[$alias_map[$id]] = $field->render($row);
|
||||
}
|
||||
$expected[] = $expected_row;
|
||||
}
|
||||
|
||||
$this->assertIdentical(Json::decode($this->drupalGet('test/serialize/field', ['query' => ['_format' => 'json']])), $this->castSafeStrings($expected));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the raw output options for row field rendering.
|
||||
*/
|
||||
public function testFieldRawOutput() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Test the UI settings for adding field ID aliases.
|
||||
$this->drupalGet('admin/structure/views/view/test_serializer_display_field/edit/rest_export_1');
|
||||
$row_options = 'admin/structure/views/nojs/display/test_serializer_display_field/rest_export_1/row_options';
|
||||
$this->assertLinkByHref($row_options);
|
||||
|
||||
// Test an empty string for an alias, this should not be used. This also
|
||||
// tests that the form can be submitted with no aliases.
|
||||
$values = [
|
||||
'row_options[field_options][created][raw_output]' => '1',
|
||||
'row_options[field_options][name][raw_output]' => '1',
|
||||
];
|
||||
$this->drupalPostForm($row_options, $values, t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
$view = Views::getView('test_serializer_display_field');
|
||||
$view->setDisplay('rest_export_1');
|
||||
$this->executeView($view);
|
||||
|
||||
$storage = $this->container->get('entity_type.manager')->getStorage('entity_test');
|
||||
|
||||
// Update the name for each to include a script tag.
|
||||
foreach ($storage->loadMultiple() as $entity_test) {
|
||||
$name = $entity_test->name->value;
|
||||
$entity_test->set('name', "<script>$name</script>");
|
||||
$entity_test->save();
|
||||
}
|
||||
|
||||
// Just test the raw 'created' value against each row.
|
||||
foreach (Json::decode($this->drupalGet('test/serialize/field', ['query' => ['_format' => 'json']])) as $index => $values) {
|
||||
$this->assertIdentical($values['created'], $view->result[$index]->views_test_data_created, 'Expected raw created value found.');
|
||||
$this->assertIdentical($values['name'], $view->result[$index]->views_test_data_name, 'Expected raw name value found.');
|
||||
}
|
||||
|
||||
// Test result with an excluded field.
|
||||
$view->setDisplay('rest_export_1');
|
||||
$view->displayHandlers->get('rest_export_1')->overrideOption('fields', [
|
||||
'name' => [
|
||||
'id' => 'name',
|
||||
'table' => 'views_test_data',
|
||||
'field' => 'name',
|
||||
'relationship' => 'none',
|
||||
],
|
||||
'created' => [
|
||||
'id' => 'created',
|
||||
'exclude' => TRUE,
|
||||
'table' => 'views_test_data',
|
||||
'field' => 'created',
|
||||
'relationship' => 'none',
|
||||
],
|
||||
]);
|
||||
$view->save();
|
||||
$this->executeView($view);
|
||||
foreach (Json::decode($this->drupalGet('test/serialize/field', ['query' => ['_format' => 'json']])) as $index => $values) {
|
||||
$this->assertTrue(!isset($values['created']), 'Excluded value not found.');
|
||||
}
|
||||
// Test that the excluded field is not shown in the row options.
|
||||
$this->drupalGet('admin/structure/views/nojs/display/test_serializer_display_field/rest_export_1/row_options');
|
||||
$this->assertNoText('created');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the live preview output for json output.
|
||||
*/
|
||||
public function testLivePreview() {
|
||||
// We set up a request so it looks like an request in the live preview.
|
||||
$request = new Request();
|
||||
$request->query->add([MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']);
|
||||
/** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */
|
||||
$request_stack = \Drupal::service('request_stack');
|
||||
$request_stack->push($request);
|
||||
|
||||
$view = Views::getView('test_serializer_display_entity');
|
||||
$view->setDisplay('rest_export_1');
|
||||
$this->executeView($view);
|
||||
|
||||
// Get the serializer service.
|
||||
$serializer = $this->container->get('serializer');
|
||||
|
||||
$entities = [];
|
||||
foreach ($view->result as $row) {
|
||||
$entities[] = $row->_entity;
|
||||
}
|
||||
|
||||
$expected = $serializer->serialize($entities, 'json');
|
||||
|
||||
$view->live_preview = TRUE;
|
||||
|
||||
$build = $view->preview();
|
||||
$rendered_json = $build['#plain_text'];
|
||||
$this->assertTrue(!isset($build['#markup']) && $rendered_json == $expected, 'Ensure the previewed json is escaped.');
|
||||
$view->destroy();
|
||||
|
||||
$expected = $serializer->serialize($entities, 'xml');
|
||||
|
||||
// Change the request format to xml.
|
||||
$view->setDisplay('rest_export_1');
|
||||
$view->getDisplay()->setOption('style', [
|
||||
'type' => 'serializer',
|
||||
'options' => [
|
||||
'uses_fields' => FALSE,
|
||||
'formats' => [
|
||||
'xml' => 'xml',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->executeView($view);
|
||||
$build = $view->preview();
|
||||
$rendered_xml = $build['#plain_text'];
|
||||
$this->assertEqual($rendered_xml, $expected, 'Ensure we preview xml when we change the request format.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the views interface for REST export displays.
|
||||
*/
|
||||
public function testSerializerViewsUI() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
// Click the "Update preview button".
|
||||
$this->drupalPostForm('admin/structure/views/view/test_serializer_display_field/edit/rest_export_1', $edit = [], t('Update preview'));
|
||||
$this->assertResponse(200);
|
||||
// Check if we receive the expected result.
|
||||
$result = $this->xpath('//div[@id="views-live-preview"]/pre');
|
||||
$json_preview = $result[0]->getText();
|
||||
$this->assertSame($json_preview, $this->drupalGet('test/serialize/field'), 'The expected JSON preview output was found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the field row style using fieldapi fields.
|
||||
*/
|
||||
public function testFieldapiField() {
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
$node = $this->drupalCreateNode();
|
||||
|
||||
$result = Json::decode($this->drupalGet('test/serialize/node-field', ['query' => ['_format' => 'json']]));
|
||||
$this->assertEqual($result[0]['nid'], $node->id());
|
||||
$this->assertEqual($result[0]['body'], $node->body->processed);
|
||||
|
||||
// Make sure that serialized fields are not exposed to XSS.
|
||||
$node = $this->drupalCreateNode();
|
||||
$node->body = [
|
||||
'value' => '<script type="text/javascript">alert("node-body");</script>' . $this->randomMachineName(32),
|
||||
'format' => filter_default_format(),
|
||||
];
|
||||
$node->save();
|
||||
$result = Json::decode($this->drupalGet('test/serialize/node-field', ['query' => ['_format' => 'json']]));
|
||||
$this->assertEqual($result[1]['nid'], $node->id());
|
||||
$this->assertTrue(strpos($this->getRawContent(), "<script") === FALSE, "No script tag is present in the raw page contents.");
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Add an alias and make the output raw.
|
||||
$row_options = 'admin/structure/views/nojs/display/test_serializer_node_display_field/rest_export_1/row_options';
|
||||
|
||||
// Test an empty string for an alias, this should not be used. This also
|
||||
// tests that the form can be submitted with no aliases.
|
||||
$this->drupalPostForm($row_options, ['row_options[field_options][title][raw_output]' => '1'], t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
$view = Views::getView('test_serializer_node_display_field');
|
||||
$view->setDisplay('rest_export_1');
|
||||
$this->executeView($view);
|
||||
|
||||
// Test the raw 'created' value against each row.
|
||||
foreach (Json::decode($this->drupalGet('test/serialize/node-field', ['query' => ['_format' => 'json']])) as $index => $values) {
|
||||
$this->assertIdentical($values['title'], $view->result[$index]->_entity->title->value, 'Expected raw title value found.');
|
||||
}
|
||||
|
||||
// Test that multiple raw body fields are shown.
|
||||
// Make the body field unlimited cardinatlity.
|
||||
$storage_definition = $node->getFieldDefinition('body')->getFieldStorageDefinition();
|
||||
$storage_definition->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
|
||||
$storage_definition->save();
|
||||
|
||||
$this->drupalPostForm($row_options, ['row_options[field_options][body][raw_output]' => '1'], t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
$node = $this->drupalCreateNode();
|
||||
|
||||
$body = [
|
||||
'value' => '<script type="text/javascript">alert("node-body");</script>' . $this->randomMachineName(32),
|
||||
'format' => filter_default_format(),
|
||||
];
|
||||
// Add two body items.
|
||||
$node->body = [$body, $body];
|
||||
$node->save();
|
||||
|
||||
$view = Views::getView('test_serializer_node_display_field');
|
||||
$view->setDisplay('rest_export_1');
|
||||
$this->executeView($view);
|
||||
|
||||
$result = Json::decode($this->drupalGet('test/serialize/node-field', ['query' => ['_format' => 'json']]));
|
||||
$this->assertEqual(count($result[2]['body']), $node->body->count(), 'Expected count of values');
|
||||
$this->assertEqual($result[2]['body'], array_map(function ($item) {
|
||||
return $item['value'];
|
||||
}, $node->body->getValue()), 'Expected raw body values found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the "Grouped rows" functionality.
|
||||
*/
|
||||
public function testGroupRows() {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = $this->container->get('renderer');
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
// Create a text field with cardinality set to unlimited.
|
||||
$field_name = 'field_group_rows';
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'node',
|
||||
'type' => 'string',
|
||||
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
|
||||
]);
|
||||
$field_storage->save();
|
||||
// Create an instance of the text field on the content type.
|
||||
$field = FieldConfig::create([
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => 'page',
|
||||
]);
|
||||
$field->save();
|
||||
$grouped_field_values = ['a', 'b', 'c'];
|
||||
$edit = [
|
||||
'title' => $this->randomMachineName(),
|
||||
$field_name => $grouped_field_values,
|
||||
];
|
||||
$this->drupalCreateNode($edit);
|
||||
$view = Views::getView('test_serializer_node_display_field');
|
||||
$view->setDisplay('rest_export_1');
|
||||
// Override the view's fields to include the field_group_rows field, set the
|
||||
// group_rows setting to true.
|
||||
$fields = [
|
||||
$field_name => [
|
||||
'id' => $field_name,
|
||||
'table' => 'node__' . $field_name,
|
||||
'field' => $field_name,
|
||||
'type' => 'string',
|
||||
'group_rows' => TRUE,
|
||||
],
|
||||
];
|
||||
$view->displayHandlers->get('default')->overrideOption('fields', $fields);
|
||||
$build = $view->preview();
|
||||
// Get the serializer service.
|
||||
$serializer = $this->container->get('serializer');
|
||||
// Check if the field_group_rows field is grouped.
|
||||
$expected = [];
|
||||
$expected[] = [$field_name => implode(', ', $grouped_field_values)];
|
||||
$this->assertEqual($serializer->serialize($expected, 'json'), (string) $renderer->renderRoot($build));
|
||||
// Set the group rows setting to false.
|
||||
$view = Views::getView('test_serializer_node_display_field');
|
||||
$view->setDisplay('rest_export_1');
|
||||
$fields[$field_name]['group_rows'] = FALSE;
|
||||
$view->displayHandlers->get('default')->overrideOption('fields', $fields);
|
||||
$build = $view->preview();
|
||||
// Check if the field_group_rows field is ungrouped and displayed per row.
|
||||
$expected = [];
|
||||
foreach ($grouped_field_values as $grouped_field_value) {
|
||||
$expected[] = [$field_name => $grouped_field_value];
|
||||
}
|
||||
$this->assertEqual($serializer->serialize($expected, 'json'), (string) $renderer->renderRoot($build));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the exposed filter works.
|
||||
*
|
||||
* There is an exposed filter on the title field which takes a title query
|
||||
* parameter. This is set to filter nodes by those whose title starts with
|
||||
* the value provided.
|
||||
*/
|
||||
public function testRestViewExposedFilter() {
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
$node0 = $this->drupalCreateNode(['title' => 'Node 1']);
|
||||
$node1 = $this->drupalCreateNode(['title' => 'Node 11']);
|
||||
$node2 = $this->drupalCreateNode(['title' => 'Node 111']);
|
||||
|
||||
// Test that no filter brings back all three nodes.
|
||||
$result = Json::decode($this->drupalGet('test/serialize/node-exposed-filter', ['query' => ['_format' => 'json']]));
|
||||
|
||||
$expected = [
|
||||
0 => [
|
||||
'nid' => $node0->id(),
|
||||
'body' => $node0->body->processed,
|
||||
],
|
||||
1 => [
|
||||
'nid' => $node1->id(),
|
||||
'body' => $node1->body->processed,
|
||||
],
|
||||
2 => [
|
||||
'nid' => $node2->id(),
|
||||
'body' => $node2->body->processed,
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertEqual($result, $expected, 'Querying a view with no exposed filter returns all nodes.');
|
||||
|
||||
// Test that title starts with 'Node 11' query finds 2 of the 3 nodes.
|
||||
$result = Json::decode($this->drupalGet('test/serialize/node-exposed-filter', ['query' => ['_format' => 'json', 'title' => 'Node 11']]));
|
||||
|
||||
$expected = [
|
||||
0 => [
|
||||
'nid' => $node1->id(),
|
||||
'body' => $node1->body->processed,
|
||||
],
|
||||
1 => [
|
||||
'nid' => $node2->id(),
|
||||
'body' => $node2->body->processed,
|
||||
],
|
||||
];
|
||||
|
||||
$cache_contexts = [
|
||||
'languages:language_content',
|
||||
'languages:language_interface',
|
||||
'theme',
|
||||
'request_format',
|
||||
'user.node_grants:view',
|
||||
'url',
|
||||
];
|
||||
|
||||
$this->assertEqual($result, $expected, 'Querying a view with a starts with exposed filter on the title returns nodes whose title starts with value provided.');
|
||||
$this->assertCacheContexts($cache_contexts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test multilingual entity rows.
|
||||
*/
|
||||
public function testMulEntityRows() {
|
||||
// Create some languages.
|
||||
ConfigurableLanguage::createFromLangcode('l1')->save();
|
||||
ConfigurableLanguage::createFromLangcode('l2')->save();
|
||||
|
||||
// Create an entity with no translations.
|
||||
$storage = \Drupal::entityTypeManager()->getStorage('entity_test_mul');
|
||||
$storage->create(['langcode' => 'l1', 'name' => 'mul-none'])->save();
|
||||
|
||||
// Create some entities with translations.
|
||||
$entity = $storage->create(['langcode' => 'l1', 'name' => 'mul-l1-orig']);
|
||||
$entity->save();
|
||||
$entity->addTranslation('l2', ['name' => 'mul-l1-l2'])->save();
|
||||
$entity = $storage->create(['langcode' => 'l2', 'name' => 'mul-l2-orig']);
|
||||
$entity->save();
|
||||
$entity->addTranslation('l1', ['name' => 'mul-l2-l1'])->save();
|
||||
|
||||
// Get the names of the output.
|
||||
$json = $this->drupalGet('test/serialize/translated_entity', ['query' => ['_format' => 'json']]);
|
||||
$decoded = $this->container->get('serializer')->decode($json, 'hal_json');
|
||||
$names = [];
|
||||
foreach ($decoded as $item) {
|
||||
$names[] = $item['name'][0]['value'];
|
||||
}
|
||||
sort($names);
|
||||
|
||||
// Check that the names are correct.
|
||||
$expected = ['mul-l1-l2', 'mul-l1-orig', 'mul-l2-l1', 'mul-l2-orig', 'mul-none'];
|
||||
$this->assertIdentical($names, $expected, 'The translated content was found in the JSON.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,9 +30,9 @@ class ConfigDependenciesTest extends KernelTestBase {
|
||||
$rest_config = RestResourceConfig::create($configuration);
|
||||
|
||||
$result = $config_dependencies->calculateDependencies($rest_config);
|
||||
$this->assertEquals(['module' => [
|
||||
'basic_auth', 'serialization', 'hal',
|
||||
]], $result);
|
||||
$this->assertEquals([
|
||||
'module' => ['basic_auth', 'serialization', 'hal'],
|
||||
], $result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,7 +49,7 @@ class RequestHandlerTest extends KernelTestBase {
|
||||
*/
|
||||
public function testHandle() {
|
||||
$request = new Request();
|
||||
$route_match = new RouteMatch('test', new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_format' => 'json']));
|
||||
$route_match = new RouteMatch('test', (new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_format' => 'json']))->setMethods(['GET']));
|
||||
|
||||
$resource = $this->prophesize(StubRequestHandlerResourcePlugin::class);
|
||||
$resource->get(NULL, $request)
|
||||
@@ -76,7 +76,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']));
|
||||
$route_match = new RouteMatch('test', (new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_content_type_format' => 'json']))->setMethods(['PATCH']));
|
||||
$request->setMethod('PATCH');
|
||||
$response = new ResourceResponse([]);
|
||||
$resource->patch(NULL, $request)
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Kernel\Views;
|
||||
|
||||
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests the auth option of rest exports.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\rest\Plugin\views\display\RestExport
|
||||
*
|
||||
* @group rest
|
||||
*/
|
||||
class RestExportAuthTest extends ViewsKernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'node',
|
||||
'rest',
|
||||
'views_ui',
|
||||
'basic_auth',
|
||||
'serialization',
|
||||
'rest',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $testViews = ['rest_export_with_authorization_correction'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->installConfig(['user']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that rest export auth settings are automatically corrected.
|
||||
*
|
||||
* @see rest_update_8401()
|
||||
* @see rest_views_presave()
|
||||
* @see \Drupal\rest\Tests\Update\RestExportAuthCorrectionUpdateTest
|
||||
*/
|
||||
public function testAuthCorrection() {
|
||||
// Get particular view.
|
||||
$view = \Drupal::entityTypeManager()
|
||||
->getStorage('view')
|
||||
->load('rest_export_with_authorization_correction');
|
||||
$displays = $view->get('display');
|
||||
$this->assertSame($displays['rest_export_1']['display_options']['auth'], ['cookie'], 'Cookie is used for authentication');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -141,8 +141,8 @@ class CollectRoutesTest extends UnitTestCase {
|
||||
$requirements_1 = $this->routes->get('test_1')->getRequirements();
|
||||
$requirements_2 = $this->routes->get('view.test_view.page_1')->getRequirements();
|
||||
|
||||
$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.');
|
||||
$this->assertEquals(0, count($requirements_1), 'First route has no requirement.');
|
||||
$this->assertEquals(1, count($requirements_2), 'Views route with rest export had the format requirement added.');
|
||||
|
||||
// Check auth options.
|
||||
$auth = $this->routes->get('view.test_view.page_1')->getOption('_auth');
|
||||
|
||||
+21
-21
@@ -79,11 +79,6 @@ class ResourceResponseSubscriberTest extends UnitTestCase {
|
||||
* @dataProvider providerTestResponseFormat
|
||||
*/
|
||||
public function testResponseFormat($methods, array $supported_formats, $request_format, array $request_headers, $request_body, $expected_response_format, $expected_response_content_type, $expected_response_content) {
|
||||
$parameters = [];
|
||||
if ($request_format !== FALSE) {
|
||||
$parameters['_format'] = $request_format;
|
||||
}
|
||||
|
||||
foreach ($request_headers as $key => $value) {
|
||||
unset($request_headers[$key]);
|
||||
$key = strtoupper(str_replace('-', '_', $key));
|
||||
@@ -91,8 +86,13 @@ class ResourceResponseSubscriberTest extends UnitTestCase {
|
||||
}
|
||||
|
||||
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';
|
||||
$request = Request::create('/rest/test', $method, [], [], [], $request_headers, $request_body);
|
||||
// \Drupal\Core\StackMiddleware\NegotiationMiddleware normally takes care
|
||||
// of this so we'll hard code it here.
|
||||
if ($request_format) {
|
||||
$request->setRequestFormat($request_format);
|
||||
}
|
||||
$route_requirement_key_format = $request->isMethodCacheable() ? '_format' : '_content_type_format';
|
||||
$route_match = new RouteMatch('test', new Route('/rest/test', ['_rest_resource_config' => $this->randomMachineName()], [$route_requirement_key_format => implode('|', $supported_formats)]));
|
||||
|
||||
$resource_response_subscriber = new ResourceResponseSubscriber(
|
||||
@@ -116,11 +116,6 @@ class ResourceResponseSubscriberTest extends UnitTestCase {
|
||||
public function testOnResponseWithCacheableResponse($methods, array $supported_formats, $request_format, array $request_headers, $request_body, $expected_response_format, $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));
|
||||
@@ -128,8 +123,13 @@ class ResourceResponseSubscriberTest extends UnitTestCase {
|
||||
}
|
||||
|
||||
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';
|
||||
$request = Request::create('/rest/test', $method, [], [], [], $request_headers, $request_body);
|
||||
// \Drupal\Core\StackMiddleware\NegotiationMiddleware normally takes care
|
||||
// of this so we'll hard code it here.
|
||||
if ($request_format) {
|
||||
$request->setRequestFormat($request_format);
|
||||
}
|
||||
$route_requirement_key_format = $request->isMethodCacheable() ? '_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)]));
|
||||
|
||||
// The RequestHandler must return a ResourceResponseInterface object.
|
||||
@@ -166,11 +166,6 @@ class ResourceResponseSubscriberTest extends UnitTestCase {
|
||||
public function testOnResponseWithUncacheableResponse($methods, array $supported_formats, $request_format, array $request_headers, $request_body, $expected_response_format, $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));
|
||||
@@ -178,8 +173,13 @@ class ResourceResponseSubscriberTest extends UnitTestCase {
|
||||
}
|
||||
|
||||
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';
|
||||
$request = Request::create('/rest/test', $method, [], [], [], $request_headers, $request_body);
|
||||
// \Drupal\Core\StackMiddleware\NegotiationMiddleware normally takes care
|
||||
// of this so we'll hard code it here.
|
||||
if ($request_format) {
|
||||
$request->setRequestFormat($request_format);
|
||||
}
|
||||
$route_requirement_key_format = $request->isMethodCacheable() ? '_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)]));
|
||||
|
||||
// The RequestHandler must return a ResourceResponseInterface object.
|
||||
|
||||
Reference in New Issue
Block a user