Issue #2909183 by Wim Leers, tedbow: Add path alias (PathItem) field PATCH test coverage

8.5.x
Nathaniel Catchpole 2017-10-17 12:15:18 +01:00
parent daf25aa9f6
commit 831450a1f2
3 changed files with 125 additions and 1 deletions

View File

@ -30,6 +30,13 @@ class PathItem extends FieldItemBase {
*/
protected $isLoaded = FALSE;
/**
* Whether the alias is currently being set.
*
* @var bool
*/
protected $isLoading = FALSE;
/**
* {@inheritdoc}
*/
@ -119,6 +126,17 @@ class PathItem extends FieldItemBase {
return parent::get($property_name);
}
/**
* {@inheritdoc}
*/
public function setValue($values, $notify = TRUE) {
// Also ensure that existing values are loaded when setting a value, this
// ensures that it is possible to set a new value immediately after loading
// an entity.
$this->ensureLoaded();
return parent::setValue($values, $notify);
}
/**
* {@inheritdoc}
*/
@ -170,7 +188,9 @@ class PathItem extends FieldItemBase {
* https://www.drupal.org/node/2392845.
*/
protected function ensureLoaded() {
if (!$this->isLoaded) {
// Make sure to avoid a infinite loop if setValue() has be called from this
// block which calls ensureLoaded().
if (!$this->isLoaded && !$this->isLoading) {
$entity = $this->getEntity();
if (!$entity->isNew()) {
// @todo Support loading languge neutral aliases in
@ -180,7 +200,9 @@ class PathItem extends FieldItemBase {
'langcode' => $this->getLangcode(),
]);
if ($alias) {
$this->isLoading = TRUE;
$this->setValue($alias);
$this->isLoading = FALSE;
}
else {
// If there is no existing alias, default the langcode to the current

View File

@ -7,6 +7,7 @@ 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 {
@ -215,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']);
}
}

View File

@ -6,6 +6,7 @@ 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 {
@ -185,4 +186,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']);
}
}