.../EntityResource/EntityResourceTestBase.php | 79 ++++++++++++++++++++-- 1 file changed, 75 insertions(+), 4 deletions(-) diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php index 421d666..09bca01 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php @@ -89,6 +89,8 @@ public function setUp() { abstract protected function getExpectedNormalizedEntity(); public function testGet() { + $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 @@ -97,12 +99,47 @@ public function testGet() { $url = $this->getUrl(); $request_options = []; - // @todo test what happens before provisioning. Edge case: node. - $this->setUpAuthorization('GET'); + // DX: 404 when resource not provisioned, 403 if canonical route. + $response = $this->request('GET', $url, $request_options); + // @todo Open issue to improve this message: it should list '/relative/url?query-string', not just '/relative/url'. + if ($has_canonical_url) { + $this->assertSame(403, $response->getStatusCode()); + } + else { + $this->assertSame(404, $response->getStatusCode()); + } + $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type')); + + + $url->setOption('query', ['_format' => static::$format]); + + + // DX: 404 when resource not provisioned, 403 if canonical route. + $response = $this->request('GET', $url, $request_options); + // @todo Open issue to improve this message: it should list '/relative/url?query-string', not just '/relative/url'. + if ($has_canonical_url) { + $this->assertResourceErrorResponse(403, '', $response); + } + else { + $this->assertResourceErrorResponse(404, 'No route found for "GET ' . str_replace($this->baseUrl, '', $this->getUrl()->setAbsolute()->toString()) . '"', $response); + } + + $this->provisionEntityResource(); - $has_canonical_url = $this->entity->hasLinkTemplate('canonical'); + + // DX: 403 when unauthorized. + $response = $this->request('GET', $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('GET'); + // Simulate the developer again forgetting the ?_format query string. + $url->setOption('query', []); + + // DX: 406 when ?_format is missing, except when requesting a canonical HTML // route. @@ -219,6 +256,8 @@ public function testPost() { return; } + $has_canonical_url = $this->entity->hasLinkTemplate('canonical'); + // Try with all of the following request bodies. $unparseable_request_body = '!{>}<'; $parseable_valid_request_body = $this->serializer->encode($this->getNormalizedEntityToCreate(), static::$format); @@ -229,16 +268,48 @@ public function testPost() { // - 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->getPostUrl()->setOption('query', ['_format' => static::$format]); + $url = $this->getPostUrl(); $request_options = []; + // DX: 404 when resource not provisioned, but HTML if canonical route. + $response = $this->request('POST', $url, $request_options); + if ($has_canonical_url) { + $this->assertSame(404, $response->getStatusCode()); + $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type')); + } + else { + $this->assertResourceErrorResponse(404, 'No route found for "GET ' . str_replace($this->baseUrl, '', $this->getUrl()->setAbsolute()->toString()) . '"', $response); + } + + + $url->setOption('query', ['_format' => static::$format]); + + // DX: 404 when resource not provisioned. $response = $this->request('POST', $url, $request_options); // @todo Open issue to improve this message: it should list '/relative/url?query-string', not just '/relative/url'. $this->assertResourceErrorResponse(404, 'No route found for "POST ' . str_replace($this->baseUrl, '', $this->getPostUrl()->setAbsolute()->toString()) . '"', $response); + $this->provisionEntityResource(); + // Simulate the developer again forgetting the ?_format query string. + $url->setOption('query', []); + + + // DX: 415 when no Content-Type request header, but HTML if canonical route. + $response = $this->request('POST', $url, $request_options); + if ($has_canonical_url) { + $this->assertSame(415, $response->getStatusCode()); + $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type')); + $this->assertTrue(FALSE !== strpos($response->getBody()->getContents(), htmlspecialchars('No "Content-Type" request header specified'))); + } + else { + $this->assertResourceErrorResponse(415, 'No "Content-Type" request header specified', $response); + } + + + $url->setOption('query', ['_format' => static::$format]); // DX: 415 when no Content-Type request header.