.../tests/src/Functional/FileUploadTest.php | 102 ++++++++++++++++++++- 1 file changed, 98 insertions(+), 4 deletions(-) diff --git a/modules/jsonapi_file_upload/tests/src/Functional/FileUploadTest.php b/modules/jsonapi_file_upload/tests/src/Functional/FileUploadTest.php index 56d1069..86009d9 100644 --- a/modules/jsonapi_file_upload/tests/src/Functional/FileUploadTest.php +++ b/modules/jsonapi_file_upload/tests/src/Functional/FileUploadTest.php @@ -133,6 +133,9 @@ class FileUploadTest extends ResourceTestBase { ->setTranslatable(FALSE); $this->field->save(); + // Reload entity so that it has the new field. + $this->entity = $this->entityStorage->loadUnchanged($this->entity->id()); + $this->rebuildAll(); } @@ -194,7 +197,7 @@ class FileUploadTest extends ResourceTestBase { } /** - * Tests using the file upload POST route. + * Tests using the file upload POST route; needs second request to "use" file. */ public function testPostFileUpload() { $uri = Url::fromUri('base:' . static::$postUri); @@ -251,6 +254,82 @@ class FileUploadTest extends ResourceTestBase { } /** + * Tests using the 'file upload and "use" file in single request" POST route. + */ + public function testPostFileUploadAndUseInSingleRequest() { + // Update the test entity so it already has a file. This allows verifying + // that this route appends files, and does not replace them. + mkdir('public://foobar'); + file_put_contents('public://foobar/existing.txt', $this->testFileData); + $existing_file = File::create([ + 'uri' => 'public://foobar/existing.txt', + ]); + $existing_file->setOwnerId($this->account->id()); + $existing_file->setPermanent(); + $existing_file->save(); + $this->entity + ->set('field_rest_file_test', ['target_id' => $existing_file->id()]) + ->save(); + + $uri = Url::fromUri('base:' . '/jsonapi/entity_test/entity_test/' . $this->entity->uuid() . '/field_rest_file_test'); + + // DX: 403 when unauthorized. + $response = $this->fileRequest($uri, $this->testFileData); + $this->assertResourceErrorResponse(403, $this->getExpectedUnauthorizedAccessMessage('PATCH'), $uri, $response); + + $this->setUpAuthorization('PATCH'); + + // 404 when the field name is invalid. + $invalid_uri = Url::fromUri($uri->getUri() . '_invalid'); + $response = $this->fileRequest($invalid_uri, $this->testFileData); + $this->assertResourceErrorResponse(404, 'Field "field_rest_file_test_invalid" does not exist', $invalid_uri, $response); + + // This request fails despite the upload succeeding, because we're not + // allowed to view the entity we're uploading to. + $response = $this->fileRequest($uri, $this->testFileData); + $this->assertResourceErrorResponse(403, $this->getExpectedUnauthorizedAccessMessage('GET'), $uri, $response, FALSE, ['4xx-response', 'http_response'], ['user.permissions']); + + $this->setUpAuthorization('GET'); + + // Reuploading the same file will result in the file being uploaded twice + // and referenced twice. + $response = $this->fileRequest($uri, $this->testFileData); + $this->assertSame(200, $response->getStatusCode()); + $expected = [ + 'jsonapi' => [ + 'meta' => [ + 'links' => [ + 'self' => ['href' => 'http://jsonapi.org/format/1.0/'], + ], + ], + 'version' => '1.0', + ], + 'links' => [ + 'self' => ['href' => Url::fromUri('base:/jsonapi/entity_test/entity_test/' . $this->entity->uuid() . '/field_rest_file_test')->setAbsolute(TRUE)->toString()], + ], + 'data' => [ + 0 => $this->getExpectedDocument(1, 'existing.txt', TRUE, TRUE)['data'], + 1 => $this->getExpectedDocument(2, 'example.txt', TRUE, TRUE)['data'], + 2 => $this->getExpectedDocument(3, 'example_0.txt', FALSE, TRUE)['data'], + ], + ]; + $this->assertResponseData($expected, $response); + + // The response document received for the POST request is identical to the + // response document received by GETting the same URL. + $request_options = []; + $request_options[RequestOptions::HEADERS]['Content-Type'] = 'application/vnd.api+json'; + $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions()); + $response = $this->request('GET', $uri, $request_options); + $this->assertSame(200, $response->getStatusCode()); + $this->assertResponseData($expected, $response); + + // Check the actual file data. + $this->assertSame($this->testFileData, file_get_contents('public://foobar/example.txt')); + $this->assertSame($this->testFileData, file_get_contents('public://foobar/example_0.txt')); + } + + /** * Returns the JSON API POST document referencing the uploaded file. * * @return array @@ -566,7 +645,16 @@ class FileUploadTest extends ResourceTestBase { * {@inheritdoc} */ protected function getExpectedUnauthorizedAccessMessage($method) { - return "The current user is not permitted to upload a file for this field. The following permissions are required: 'administer entity_test content' OR 'administer entity_test_with_bundle content' OR 'create entity_test entity_test_with_bundle entities'."; + switch ($method) { + case 'GET': + return "The current user is not allowed to view this relationship. The 'view test entity' permission is required."; + + case 'POST': + return "The current user is not permitted to upload a file for this field. The following permissions are required: 'administer entity_test content' OR 'administer entity_test_with_bundle content' OR 'create entity_test entity_test_with_bundle entities'."; + + case 'PATCH': + return "The current user is not permitted to upload a file for this field. The 'administer entity_test content' permission is required."; + } } /** @@ -578,11 +666,13 @@ class FileUploadTest extends ResourceTestBase { * The expected filename for the stored file. * @param bool $expected_as_filename * Whether the expected filename should be the filename property too. + * @param bool $expected_status + * The expected file status. Defaults to FALSE. * * @return array * A JSON API response document. */ - protected function getExpectedDocument($fid = 1, $expected_filename = 'example.txt', $expected_as_filename = FALSE) { + protected function getExpectedDocument($fid = 1, $expected_filename = 'example.txt', $expected_as_filename = FALSE, $expected_status = FALSE) { $author = User::load($this->account->id()); $file = File::load($fid); $self_url = Url::fromUri('base:/jsonapi/file/file/' . $file->uuid())->setAbsolute()->toString(TRUE)->getGeneratedUrl(); @@ -612,7 +702,7 @@ class FileUploadTest extends ResourceTestBase { 'filename' => $expected_as_filename ? $expected_filename : 'example.txt', 'filesize' => strlen($this->testFileData), 'langcode' => 'en', - 'status' => FALSE, + 'status' => $expected_status, 'uri' => [ 'value' => 'public://foobar/' . $expected_filename, 'url' => base_path() . $this->siteDirectory . '/files/foobar/' . rawurlencode($expected_filename), @@ -677,6 +767,10 @@ class FileUploadTest extends ResourceTestBase { case 'POST': $this->grantPermissionsToTestedRole(['create entity_test entity_test_with_bundle entities', 'access content']); break; + + case 'PATCH': + $this->grantPermissionsToTestedRole(['administer entity_test content', 'access content']); + break; } }