tests/src/Functional/DateFormatTest.php | 5 ++ tests/src/Functional/MenuTest.php | 5 ++ tests/src/Functional/ResourceResponseTestTrait.php | 2 +- tests/src/Functional/ResourceTestBase.php | 74 +++++++++++++++------- tests/src/Functional/UserTest.php | 5 ++ 5 files changed, 66 insertions(+), 25 deletions(-) diff --git a/tests/src/Functional/DateFormatTest.php b/tests/src/Functional/DateFormatTest.php index 1b94ebe..403fb9a 100644 --- a/tests/src/Functional/DateFormatTest.php +++ b/tests/src/Functional/DateFormatTest.php @@ -29,6 +29,11 @@ class DateFormatTest extends ResourceTestBase { /** * {@inheritdoc} + */ + protected static $anonymousUsersCanViewLabels = TRUE; + + /** + * {@inheritdoc} * * @var \Drupal\Core\Datetime\DateFormatInterface */ diff --git a/tests/src/Functional/MenuTest.php b/tests/src/Functional/MenuTest.php index ea7e8c2..b16ffce 100644 --- a/tests/src/Functional/MenuTest.php +++ b/tests/src/Functional/MenuTest.php @@ -29,6 +29,11 @@ class MenuTest extends ResourceTestBase { /** * {@inheritdoc} + */ + protected static $anonymousUsersCanViewLabels = TRUE; + + /** + * {@inheritdoc} * * @var \Drupal\system\MenuInterface */ diff --git a/tests/src/Functional/ResourceResponseTestTrait.php b/tests/src/Functional/ResourceResponseTestTrait.php index 02bdba6..ca66752 100644 --- a/tests/src/Functional/ResourceResponseTestTrait.php +++ b/tests/src/Functional/ResourceResponseTestTrait.php @@ -27,7 +27,7 @@ trait ResourceResponseTestTrait { * objects. Not necessarily to a response to a collection route. In both * cases, the document should indistinguishable. * - * @param array $responses + * @param \Drupal\jsonapi\ResourceResponse[] $responses * An array or ResourceResponses to be merged. * @param string|null $self_link * The self link for the merged document if one should be set. diff --git a/tests/src/Functional/ResourceTestBase.php b/tests/src/Functional/ResourceTestBase.php index b9ccbe0..70ebfbf 100644 --- a/tests/src/Functional/ResourceTestBase.php +++ b/tests/src/Functional/ResourceTestBase.php @@ -123,6 +123,13 @@ abstract class ResourceTestBase extends BrowserTestBase { protected static $labelFieldName = NULL; /** + * Whether aononymous users can view labels of this resource type. + * + * @var bool + */ + protected static $anonymousUsersCanViewLabels = FALSE; + + /** * The entity being tested. * * @var \Drupal\Core\Entity\EntityInterface @@ -482,6 +489,9 @@ abstract class ResourceTestBase extends BrowserTestBase { protected static function getExpectedCollectionCacheability(array $collection, array $sparse_fieldset = NULL, AccountInterface $account) { $cacheability = array_reduce($collection, function (CacheableMetadata $cacheability, EntityInterface $entity) use ($sparse_fieldset, $account) { $access_result = static::entityAccess($entity, 'view', $account); + if (!$access_result->isAllowed()) { + $access_result = static::entityAccess($entity, 'view label', $account)->addCacheableDependency($access_result); + } $cacheability->addCacheableDependency($access_result); if ($access_result->isAllowed()) { $cacheability->addCacheableDependency($entity); @@ -879,33 +889,49 @@ abstract class ResourceTestBase extends BrowserTestBase { $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json'; $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions()); - // DX: 403 when unauthorized. + // DX: 403 when unauthorized, or 200 if the 'view label' operation is + // supported by the entity type. $response = $this->request('GET', $url, $request_options); - $expected_403_cacheability = $this->getExpectedUnauthorizedAccessCacheability(); - $reason = $this->getExpectedUnauthorizedAccessMessage('GET'); - // @todo Remove $expected + assertResourceResponse() in favor of the commented line below once https://www.drupal.org/project/jsonapi/issues/2943176 lands. - $expected_document = [ - 'errors' => [ - [ - 'title' => 'Forbidden', - 'status' => 403, - 'detail' => "The current user is not allowed to GET the selected resource." . (strlen($reason) ? ' ' . $reason : ''), - 'links' => [ - 'info' => HttpExceptionNormalizer::getInfoUrl(403), - ], - 'code' => 0, - 'id' => '/' . static::$resourceTypeName . '/' . $this->entity->uuid(), - 'source' => [ - 'pointer' => '/data', + if (!static::$anonymousUsersCanViewLabels) { + $expected_403_cacheability = $this->getExpectedUnauthorizedAccessCacheability(); + $reason = $this->getExpectedUnauthorizedAccessMessage('GET'); + // @todo Remove $expected + assertResourceResponse() in favor of the commented line below once https://www.drupal.org/project/jsonapi/issues/2943176 lands. + $expected_document = [ + 'errors' => [ + [ + 'title' => 'Forbidden', + 'status' => 403, + 'detail' => "The current user is not allowed to GET the selected resource." . (strlen($reason) ? ' ' . $reason : ''), + 'links' => [ + 'info' => HttpExceptionNormalizer::getInfoUrl(403), + ], + 'code' => 0, + 'id' => '/' . static::$resourceTypeName . '/' . $this->entity->uuid(), + 'source' => [ + 'pointer' => '/data', + ], ], ], - ], - ]; - $this->assertResourceResponse(403, $expected_document, $response); - /* $this->assertResourceErrorResponse(403, "The current user is not allowed to GET the selected resource." . (strlen($reason) ? ' ' . $reason : ''), $response, '/data'); */ - // @todo Uncomment in https://www.drupal.org/project/jsonapi/issues/2929428. - /* $this->assertResourceResponse(403, $expected_document, $response, $expected_403_cacheability->getCacheTags(), $expected_403_cacheability->getCacheContexts(), FALSE, 'MISS'); */ - $this->assertArrayNotHasKey('Link', $response->getHeaders()); + ]; + $this->assertResourceResponse(403, $expected_document, $response); + /* $this->assertResourceErrorResponse(403, "The current user is not allowed to GET the selected resource." . (strlen($reason) ? ' ' . $reason : ''), $response, '/data'); */ + // @todo Uncomment in https://www.drupal.org/project/jsonapi/issues/2929428. + /* $this->assertResourceResponse(403, $expected_document, $response, $expected_403_cacheability->getCacheTags(), $expected_403_cacheability->getCacheContexts(), FALSE, 'MISS'); */ + $this->assertArrayNotHasKey('Link', $response->getHeaders()); + } + else { + $label_field_name = $this->entity->getEntityType()->getKey('label'); + // @todo Fix Entity/Field API and User module in Drupal core so that despite + // there being a label callback, we can also still figure out that "name" is + // the 'label' entity key. + if ($this->entity->getEntityTypeId() === 'user') { + $label_field_name = 'name'; + } + $expected_document = $this->getExpectedDocument(); + $expected_document['data']['attributes'] = array_intersect_key($expected_document['data']['attributes'], [$label_field_name => TRUE]); + unset($expected_document['data']['relationships']); + $this->assertResourceResponse(200, $expected_document, $response, $this->getExpectedCacheTags(), $this->getExpectedCacheContexts(), FALSE, 'MISS'); + } $this->setUpAuthorization('GET'); diff --git a/tests/src/Functional/UserTest.php b/tests/src/Functional/UserTest.php index 231ac16..261a493 100644 --- a/tests/src/Functional/UserTest.php +++ b/tests/src/Functional/UserTest.php @@ -43,6 +43,11 @@ class UserTest extends ResourceTestBase { /** * {@inheritdoc} + */ + protected static $anonymousUsersCanViewLabels = TRUE; + + /** + * {@inheritdoc} * * @var \Drupal\taxonomy\TermInterface */