.../Comment/CommentResourceTestBase.php | 1 + .../EntityResource/EntityResourceTestBase.php | 98 ++++++++++++++++++++++ .../EntityTest/EntityTestResourceTestBase.php | 1 + .../EntityResource/Node/NodeResourceTestBase.php | 15 ++-- .../EntityResource/Term/TermResourceTestBase.php | 19 +++-- .../EntityResource/User/UserResourceTestBase.php | 3 +- 6 files changed, 121 insertions(+), 16 deletions(-) diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php index 871d5b7..d602524 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php @@ -36,6 +36,7 @@ protected function setUpAuthorization($method) { $this->grantPermissionsToTestedRole(['post comments']); break; case 'PATCH': + case 'DELETE': $this->grantPermissionsToTestedRole(['administer comments']); break; } diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php index e984d7f..18a61c9 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php @@ -691,6 +691,104 @@ public function testPatch() { $this->assertResourceResponse(200, FALSE, $response); } + public function testDelete() { + // @todo Remove this in https://www.drupal.org/node/2300677. + if ($this->entity instanceof ConfigEntityInterface) { + $this->assertTrue(TRUE, 'DELETEing config entities is not yet supported.'); + return; + } + + $this->initAuthentication(); + $has_canonical_url = $this->entity->hasLinkTemplate('canonical'); + + // The URL and Guzzle request options that will be used in this test. The + // request options will be modified/expanded throughout this test: + // - to first test all mistakes a developer might make, and assert that the + // error responses provide a good DX + // - to eventually result in a well-formed request that succeeds. + $url = $this->getUrl(); + $request_options = []; + + + // DX: 405 when resource not provisioned, but HTML if canonical route. + $response = $this->request('DELETE', $url, $request_options); + if ($has_canonical_url) { + $this->assertSame(405, $response->getStatusCode()); + $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type')); + } + else { + $this->assertResourceErrorResponse(404, 'No route found for "DELETE ' . str_replace($this->baseUrl, '', $this->getUrl()->setAbsolute()->toString()) . '"', $response); + } + + + $url->setOption('query', ['_format' => static::$format]); + + + // DX: 405 when resource not provisioned. + $response = $this->request('DELETE', $url, $request_options); + // @todo Open issue to improve this message: it should list '/relative/url?query-string', not just '/relative/url'. + $this->assertResourceErrorResponse(405, 'No route found for "DELETE ' . str_replace($this->baseUrl, '', $this->getUrl()->setAbsolute()->toString()) . '": Method Not Allowed (Allow: GET, POST, HEAD)', $response); + + + $this->provisionEntityResource(); + + + if (static::$auth) { + // DX: forgetting authentication: authentication provider-specific error + // response. + $response = $this->request('DELETE', $url, $request_options); + $this->assertResponseWhenMissingAuthentication($response); + } + + + $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH')); + + + // DX: 403 when unauthorized. + $response = $this->request('DELETE', $url, $request_options); + // @todo Update this to the improved error message when https://www.drupal.org/node/2808233 lands. + $this->assertResourceErrorResponse(403, '', $response); + + + $this->setUpAuthorization('DELETE'); + + + // Before sending a well-formed request, allow the authentication provider's + // edge cases to also be tested. + $this->assertAuthenticationEdgeCases('DELETE', $url, $request_options); + + + // 204 for well-formed request. + $response = $this->request('DELETE', $url, $request_options); + $this->assertSame(204, $response->getStatusCode()); + // @todo Uncomment the following line when https://www.drupal.org/node/2821711 is fixed. +// $this->assertSame(FALSE, $response->hasHeader('Content-Type')); + $this->assertSame('', $response->getBody()->getContents()); + + + $this->config('rest.settings')->set('bc_entity_resource_permissions', TRUE)->save(TRUE); + // @todo Remove this in https://www.drupal.org/node/2815845. + drupal_flush_all_caches(); + $this->entity = $this->createEntity(); + $url = $this->getUrl()->setOption('query', $url->getOption('query')); + + + // DX: 403 when unauthorized. + $response = $this->request('DELETE', $url, $request_options); + $this->assertResourceErrorResponse(403, '', $response); + + + $this->grantPermissionsToTestedRole(['restful delete entity:' . static::$entityType]); + + + // 204 for well-formed request. + $response = $this->request('DELETE', $url, $request_options); + $this->assertSame(204, $response->getStatusCode()); + // @todo Uncomment the following line when https://www.drupal.org/node/2821711 is fixed. +// $this->assertSame(FALSE, $response->hasHeader('Content-Type')); + $this->assertSame('', $response->getBody()->getContents()); + } + /** * Gets an entity resource's POST URL. * diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestResourceTestBase.php index 418f6ee..5dff569 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestResourceTestBase.php @@ -30,6 +30,7 @@ protected function setUpAuthorization($method) { $this->grantPermissionsToTestedRole(['create entity_test entity_test_with_bundle entities']); break; case 'PATCH': + case 'DELETE': $this->grantPermissionsToTestedRole(['administer entity_test content']); break; } diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php index 28d2807..ba1ec18 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php @@ -33,6 +33,9 @@ protected function setUpAuthorization($method) { case 'PATCH': $this->grantPermissionsToTestedRole(['access content', 'edit any camelids content']); break; + case 'DELETE': + $this->grantPermissionsToTestedRole(['access content', 'delete any camelids content']); + break; } } @@ -40,11 +43,13 @@ protected function setUpAuthorization($method) { * {@inheritdoc} */ protected function createEntity() { - // Create a "Camelids" node type. - NodeType::create([ - 'name' => 'Camelids', - 'type' => 'camelids', - ])->save(); + if (!NodeType::load('camelids')) { + // Create a "Camelids" node type. + NodeType::create([ + 'name' => 'Camelids', + 'type' => 'camelids', + ])->save(); + } // Create a "Llama" node. $node = Node::create(['type' => 'camelids']); diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Term/TermResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/Term/TermResourceTestBase.php index 81b4af1..7c9f0f2 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/Term/TermResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/Term/TermResourceTestBase.php @@ -27,10 +27,8 @@ protected function setUpAuthorization($method) { $this->grantPermissionsToTestedRole(['access content']); break; case 'POST': - // @todo Create issue similar to https://www.drupal.org/node/2808217. - $this->grantPermissionsToTestedRole(['administer taxonomy']); - break; case 'PATCH': + case 'DELETE': // @todo Create issue similar to https://www.drupal.org/node/2808217. $this->grantPermissionsToTestedRole(['administer taxonomy']); break; @@ -41,12 +39,15 @@ protected function setUpAuthorization($method) { * {@inheritdoc} */ protected function createEntity() { - // Create a "Camelids" vocabulary. - $vocabulary = Vocabulary::create([ - 'name' => 'Camelids', - 'vid' => 'camelids', - ]); - $vocabulary->save(); + $vocabulary = Vocabulary::load('camelids'); + if (!$vocabulary) { + // Create a "Camelids" vocabulary. + $vocabulary = Vocabulary::create([ + 'name' => 'Camelids', + 'vid' => 'camelids', + ]); + $vocabulary->save(); + } // Create a "Llama" taxonomy term. $term = Term::create(['vid' => $vocabulary->id()]) diff --git a/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php index 264de57..fa6f32c 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php @@ -41,9 +41,8 @@ protected function setUpAuthorization($method) { $this->grantPermissionsToTestedRole(['access user profiles']); break; case 'POST': - $this->grantPermissionsToTestedRole(['administer users']); - break; case 'PATCH': + case 'DELETE': $this->grantPermissionsToTestedRole(['administer users']); break; }