diff --git a/tests/modules/jsonapi_test_field_access/jsonapi_test_field_access.permissions.yml b/tests/modules/jsonapi_test_field_access/jsonapi_test_field_access.permissions.yml deleted file mode 100644 index 18780ca..0000000 --- a/tests/modules/jsonapi_test_field_access/jsonapi_test_field_access.permissions.yml +++ /dev/null @@ -1,7 +0,0 @@ -field_jsonapi_test_entity_ref update access: - description: 'Gives access to to PATCH, POST or DELETE values of the relationship test field.' - title: 'Update JSON API relationship test field' - -field_jsonapi_test_entity_ref edit access: - description: 'Gives access to to PATCH, POST or DELETE values of the relationship test field.' - title: 'Update JSON API relationship test field' diff --git a/tests/src/Functional/ResourceTestBase.php b/tests/src/Functional/ResourceTestBase.php index 8d65f2c..3470b6d 100644 --- a/tests/src/Functional/ResourceTestBase.php +++ b/tests/src/Functional/ResourceTestBase.php @@ -1352,7 +1352,7 @@ abstract class ResourceTestBase extends BrowserTestBase { } /** - * Performs one round of relationship POST route testing. + * Performs one round of relationship POST, PATCH and DELETE route testing. * * @param array $request_options * Request options to apply. @@ -1383,6 +1383,9 @@ abstract class ResourceTestBase extends BrowserTestBase { // Test POST: empty body. $response = $this->request('POST', $url, $request_options); $this->assertResourceErrorResponse(400, 'Empty request body.', $response); + // Test PATCH: empty body. + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceErrorResponse(400, 'Empty request body.', $response); // Test POST: empty data. $request_options[RequestOptions::BODY] = Json::encode(['data' => []]); @@ -1390,22 +1393,41 @@ abstract class ResourceTestBase extends BrowserTestBase { // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2977653. $this->assertResourceResponse(201, FALSE, $response); // $this->assertResourceResponse(204, NULL, $response); + // Test PATCH: empty data. + $request_options[RequestOptions::BODY] = Json::encode(['data' => []]); + $response = $this->request('PATCH', $url, $request_options); + // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2977653. + $expected_document = $this->getExpectedGetRelationshipDocument($relationship_field_name, $resource); + $this->assertResourceResponse(200, $expected_document, $response); + //$this->assertResourceResponse(204, NULL, $response); // Test POST: data as resource identifier, not array of identifiers. $request_options[RequestOptions::BODY] = Json::encode(['data' => $target_identifier]); $response = $this->request('POST', $url, $request_options); $this->assertResourceErrorResponse(400, 'Invalid body payload for the relationship.', $response); + // Test PATCH: data as resource identifier, not array of identifiers. + $request_options[RequestOptions::BODY] = Json::encode(['data' => $target_identifier]); + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceErrorResponse(400, 'Invalid body payload for the relationship.', $response); - // Test POST: missing field. + // Test POST: missing the 'type' field. $request_options[RequestOptions::BODY] = Json::encode(['data' => array_intersect_key($target_identifier, ['id' => 'id'])]); $response = $this->request('POST', $url, $request_options); $this->assertResourceErrorResponse(400, 'Invalid body payload for the relationship.', $response); + // Test PATCH: missing the 'type' field. + $request_options[RequestOptions::BODY] = Json::encode(['data' => array_intersect_key($target_identifier, ['id' => 'id'])]); + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceErrorResponse(400, 'Invalid body payload for the relationship.', $response); - // Test POST: invalid target. // If the base resource type is the same as that of the target's (as it // will be for `user--user`), then the validity error will not be // triggered, needlessly failing this assertion. if (static::$resourceTypeName !== $target_identifier['type']) { + // Test POST: invalid target. + $request_options[RequestOptions::BODY] = Json::encode(['data' => [$resource_identifier]]); + $response = $this->request('POST', $url, $request_options); + $this->assertResourceErrorResponse(400, sprintf('The provided type (%s) does not mach the destination resource types (%s).', $resource_identifier['type'], $target_identifier['type']), $response); + // Test PATCH: invalid target. $request_options[RequestOptions::BODY] = Json::encode(['data' => [$resource_identifier]]); $response = $this->request('POST', $url, $request_options); $this->assertResourceErrorResponse(400, sprintf('The provided type (%s) does not mach the destination resource types (%s).', $resource_identifier['type'], $target_identifier['type']), $response); @@ -1425,7 +1447,16 @@ abstract class ResourceTestBase extends BrowserTestBase { //$response = $this->request('POST', $url, $request_options); //$this->assertResourceResponse(204, NULL, $response); - //// Test POST: success, relationship already exists, with unique arity. + // Test PATCH: success, new value is the same as existing value. + $request_options[RequestOptions::BODY] = Json::encode(['data' => [$target_identifier]]); + $response = $this->request('PATCH', $url, $request_options); + $resource->set($relationship_field_name, [$target_resource]); + $expected_document = $this->getExpectedGetRelationshipDocument($relationship_field_name, $resource); + // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2977653. + $this->assertResourceResponse(200, $expected_document, $response); + // $this->assertResourceResponse(204, NULL, $response); + + // Test POST: success, relationship already exists, with unique arity. $request_options[RequestOptions::BODY] = Json::encode([ 'data' => [ $target_identifier + ['meta' => ['arity' => 1]] @@ -1436,11 +1467,74 @@ abstract class ResourceTestBase extends BrowserTestBase { $expected_document = $this->getExpectedGetRelationshipDocument($relationship_field_name, $resource); $expected_document['data'][0] += ['meta' => ['arity' => 0]]; $expected_document['data'][1] += ['meta' => ['arity' => 1]]; - // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2977653. + // 200 with response body because the request did not include the + // existing relationship resource identifier object. + // @todo Remove line below in favor of commented assertion in https://www.drupal.org/project/jsonapi/issues/2977653. $this->assertResourceResponse(201, $expected_document, $response); - //// 200 with response body because the request did not include the - //// existing relationship resource identifier object. //$this->assertResourceResponse(200, $expected_document, $response); + + // @todo: Uncomment the following block in https://www.drupal.org/project/jsonapi/issues/2977659. + //// Test DELETE: two existing relationships, one removed. + //$request_options[RequestOptions::BODY] = Json::encode(['data' => [ + // $target_identifier + ['meta' => ['arity' => 0]], + //]]); + //$response = $this->request('DELETE', $url, $request_options); + //// @todo Remove 3 lines below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2977653. + //$resource->set($relationship_field_name, [$target_resource]); + //$expected_document = $this->getExpectedGetRelationshipDocument($relationship_field_name, $resource); + //$this->assertResourceResponse(201, $expected_document, $response); + //// $this->assertResourceResponse(204, NULL, $response); + //$resource->set($relationship_field_name, [$target_resource]); + //$expected_document = $this->getExpectedGetRelationshipDocument($relationship_field_name, $resource); + //$response = $this->request('GET', $url, $request_options); + //$this->assertSameDocument($expected_document, Json::decode((string) $response->getBody())); + + // Test DELETE: one existing relationship, removed. + $request_options[RequestOptions::BODY] = Json::encode(['data' => [$target_identifier]]); + $response = $this->request('DELETE', $url, $request_options); + $resource->set($relationship_field_name, []); + $expected_document = $this->getExpectedGetRelationshipDocument($relationship_field_name, $resource); + // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2977653. + $this->assertResourceResponse(201, $expected_document, $response); + // $this->assertResourceResponse(204, NULL, $response); + $expected_document = $this->getExpectedGetRelationshipDocument($relationship_field_name, $resource); + $response = $this->request('GET', $url, $request_options); + $this->assertSameDocument($expected_document, Json::decode((string) $response->getBody())); + + // Test DELETE: no existing relationships, no op, success. + $request_options[RequestOptions::BODY] = Json::encode(['data' => [$target_identifier]]); + $response = $this->request('DELETE', $url, $request_options); + // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2977653. + $this->assertResourceResponse(201, $expected_document, $response); + // $this->assertResourceResponse(204, NULL, $response); + $expected_document = $this->getExpectedGetRelationshipDocument($relationship_field_name, $resource); + $response = $this->request('GET', $url, $request_options); + $this->assertSameDocument($expected_document, Json::decode((string) $response->getBody())); + + // Test PATCH: success, new value is different than existing value. + $request_options[RequestOptions::BODY] = Json::encode(['data' => [$target_identifier, $target_identifier]]); + $response = $this->request('PATCH', $url, $request_options); + $resource->set($relationship_field_name, [$target_resource, $target_resource]); + $expected_document = $this->getExpectedGetRelationshipDocument($relationship_field_name, $resource); + $expected_document['data'][0] += ['meta' => ['arity' => 0]]; + $expected_document['data'][1] += ['meta' => ['arity' => 1]]; + // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2977653. + $this->assertResourceResponse(200, $expected_document, $response); + // $this->assertResourceResponse(204, NULL, $response); + + // Test DELETE: two existing relationships, both removed because no arity + // was specified. + $request_options[RequestOptions::BODY] = Json::encode(['data' => [$target_identifier]]); + $response = $this->request('DELETE', $url, $request_options); + $resource->set($relationship_field_name, []); + $expected_document = $this->getExpectedGetRelationshipDocument($relationship_field_name, $resource); + // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2977653. + $this->assertResourceResponse(201, $expected_document, $response); + // $this->assertResourceResponse(204, NULL, $response); + $resource->set($relationship_field_name, []); + $expected_document = $this->getExpectedGetRelationshipDocument($relationship_field_name, $resource); + $response = $this->request('GET', $url, $request_options); + $this->assertSameDocument($expected_document, Json::decode((string) $response->getBody())); } else { $request_options[RequestOptions::BODY] = Json::encode(['data' => [$target_identifier]]); @@ -1448,6 +1542,10 @@ abstract class ResourceTestBase extends BrowserTestBase { $message = 'The current user is not allowed to update this relationship.'; $message .= ($reason = $update_access->getReason()) ? ' ' . $reason : ''; $this->assertResourceErrorResponse(403, $message, $response, $relationship_field_name); + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceErrorResponse(403, $message, $response, $relationship_field_name); + $response = $this->request('DELETE', $url, $request_options); + $this->assertResourceErrorResponse(403, $message, $response, $relationship_field_name); } // Remove the test entities that were created.