View source
<?php
namespace Drupal\Tests\graphql\Kernel\Framework;
use Drupal\Core\Lock\LockBackendInterface;
use Drupal\graphql\GraphQL\Utility\FileUpload;
use Drupal\Tests\graphql\Kernel\GraphQLTestBase;
use Prophecy\Argument;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class UploadFileServiceTest extends GraphQLTestBase {
protected static $modules = [
'file',
'graphql_file_validate',
];
protected $uploadService;
protected function getSourceTestFilePath(string $filename) : string {
$file_system = $this->container
->get('file_system');
$filepath = $file_system
->getTempDirectory() . '/' . $filename;
touch($filepath);
return $filepath;
}
protected function setUp() : void {
parent::setUp();
$this
->installEntitySchema('file');
$this
->installSchema('file', [
'file_usage',
]);
$this->uploadService = $this->container
->get('graphql.file_upload');
}
public function testSuccess() : void {
$uploadFile = $this
->getUploadedFile(UPLOAD_ERR_OK);
$file_upload_response = $this->uploadService
->saveFileUpload($uploadFile, [
'uri_scheme' => 'public',
'file_directory' => 'test',
]);
$file_entity = $file_upload_response
->getFileEntity();
$this
->assertSame('public://test/test.txt', $file_entity
->getFileUri());
$this
->assertFileExists($file_entity
->getFileUri());
}
public function testFileTooLarge() : void {
$uploadFile = $this
->getUploadedFile(UPLOAD_ERR_INI_SIZE);
$file_upload_response = $this->uploadService
->saveFileUpload($uploadFile, [
'uri_scheme' => 'public',
'file_directory' => 'test',
]);
$violations = $file_upload_response
->getViolations();
$this
->assertStringMatchesFormat('The file test.txt could not be saved because it exceeds %d %s, the maximum allowed size for uploads.', $violations[0]['message']);
}
public function testPartialFile() : void {
$uploadFile = $this
->getUploadedFile(UPLOAD_ERR_PARTIAL);
$file_upload_response = $this->uploadService
->saveFileUpload($uploadFile, [
'uri_scheme' => 'public',
'file_directory' => 'test',
]);
$violations = $file_upload_response
->getViolations();
$this
->assertStringMatchesFormat('The file "test.txt" could not be saved because the upload did not complete.', $violations[0]['message']);
}
public function testMissingSettings() : void {
$uploadFile = $this
->getUploadedFile(UPLOAD_ERR_OK);
$this
->expectException(\RuntimeException::class);
$this->uploadService
->saveFileUpload($uploadFile, []);
}
public function testSizeValidation() : void {
$uploadFile = $this
->getUploadedFile(UPLOAD_ERR_OK, 4);
file_put_contents($uploadFile
->getRealPath(), 'test');
$file_upload_response = $this->uploadService
->saveFileUpload($uploadFile, [
'uri_scheme' => 'public',
'file_directory' => 'test',
'max_filesize' => 1,
]);
$violations = $file_upload_response
->getViolations();
$this
->assertStringMatchesFormat('The file is <em class="placeholder">4 bytes</em> exceeding the maximum file size of <em class="placeholder">1 byte</em>.', $violations[0]['message']);
}
public function testExtensionRenaming() : void {
$uploadFile = $this
->getUploadedFile(UPLOAD_ERR_OK, 0, 'test.php');
$file_upload_response = $this->uploadService
->saveFileUpload($uploadFile, [
'uri_scheme' => 'public',
'file_directory' => 'test',
]);
$file_entity = $file_upload_response
->getFileEntity();
$this
->assertSame('public://test/test.php_.txt', $file_entity
->getFileUri());
$this
->assertFileExists($file_entity
->getFileUri());
}
public function testExtensionValidation() : void {
$uploadFile = $this
->getUploadedFile(UPLOAD_ERR_OK, 0, 'test.txt');
$file_upload_response = $this->uploadService
->saveFileUpload($uploadFile, [
'uri_scheme' => 'public',
'file_directory' => 'test',
'file_extensions' => 'odt',
]);
$violations = $file_upload_response
->getViolations();
$this
->assertStringMatchesFormat('Only files with the following extensions are allowed: <em class="placeholder">odt</em>.', $violations[0]['message']);
}
public function testLockReleased() : void {
$lock = $this
->prophesize(LockBackendInterface::class);
$lock
->acquire(Argument::any())
->willReturn(TRUE);
$lock
->release(Argument::any())
->shouldBeCalled();
$upload_service = new FileUpload(\Drupal::service('entity_type.manager'), \Drupal::service('current_user'), \Drupal::service('file.mime_type.guesser'), \Drupal::service('file_system'), \Drupal::service('logger.channel.graphql'), \Drupal::service('token'), $lock
->reveal(), \Drupal::service('config.factory'), \Drupal::service('renderer'));
$uploadFile = $this
->getUploadedFile(UPLOAD_ERR_OK, 4);
file_put_contents($uploadFile
->getRealPath(), 'test');
$upload_service
->saveFileUpload($uploadFile, [
'uri_scheme' => 'public',
'file_directory' => 'test',
'max_filesize' => 1,
]);
}
public function testSuccessWithMultipleFileUploads() : void {
$uploadFiles = [
$this
->getUploadedFile(UPLOAD_ERR_OK, 0, 'test1.txt', 'graphql_upload_test1.txt'),
$this
->getUploadedFile(UPLOAD_ERR_OK, 0, 'test2.txt', 'graphql_upload_test2.txt'),
$this
->getUploadedFile(UPLOAD_ERR_OK, 0, 'test3.txt', 'graphql_upload_test3.txt'),
];
$file_upload_response = $this->uploadService
->saveMultipleFileUploads($uploadFiles, [
'uri_scheme' => 'public',
'file_directory' => 'test',
'file_extensions' => 'txt',
]);
$violations = $file_upload_response
->getViolations();
$this
->assertEmpty($violations);
$file_entities = $file_upload_response
->getFileEntities();
$this
->assertCount(3, $file_entities);
foreach ($file_entities as $index => $file_entity) {
$this
->assertSame('public://test/test' . ($index + 1) . '.txt', $file_entity
->getFileUri());
$this
->assertFileExists($file_entity
->getFileUri());
}
}
public function testUnsuccessWithMultipleFileUploads() : void {
$uploadFiles = [
$this
->getUploadedFile(UPLOAD_ERR_OK, 0, 'test1.txt', 'graphql_upload_test1.txt'),
$this
->getUploadedFile(UPLOAD_ERR_OK, 0, 'test2.txt', 'graphql_upload_test2.txt'),
$this
->getUploadedFile(UPLOAD_ERR_OK, 0, 'test3.jpg', 'graphql_upload_test3.jpg'),
];
$file_upload_response = $this->uploadService
->saveMultipleFileUploads($uploadFiles, [
'uri_scheme' => 'public',
'file_directory' => 'test',
'file_extensions' => 'txt',
]);
$violations = $file_upload_response
->getViolations();
$this
->assertStringMatchesFormat('Only files with the following extensions are allowed: <em class="placeholder">txt</em>.', $violations[0]['message']);
$file_entities = $file_upload_response
->getFileEntities();
$this
->assertEmpty($file_entities);
}
protected function getUploadedFile(int $error_status, int $size = 0, string $dest_filename = 'test.txt', string $source_filename = 'graphql_upload_test.txt') : UploadedFile {
$source_filepath = $this
->getSourceTestFilePath($source_filename);
[
$version,
] = explode('.', \Drupal::VERSION, 2);
switch ($version) {
case 8:
return new UploadedFile($source_filepath, $dest_filename, 'text/plain', $size, $error_status, TRUE);
}
return new UploadedFile($source_filepath, $dest_filename, 'text/plain', $error_status, TRUE);
}
}