From b54976216c83a100e9587aeea0aa823e9b7b3e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20G=C3=B6r=C3=B6g?= Date: Sat, 13 Jun 2020 17:25:48 +0200 Subject: [PATCH 1/3] Add ng-file-upload driver --- README.md | 8 + config/chunk-uploader.php | 4 +- examples/ng-file-upload.blade.php | 49 ++++ src/Driver/NgFileUploadDriver.php | 174 ++++++++++++++ src/Range/NgFileUploadRange.php | 95 ++++++++ src/UploadManager.php | 9 + tests/Driver/NgFileUploadDriverTest.php | 291 ++++++++++++++++++++++++ tests/Range/NgFileUploadRangeTest.php | 128 +++++++++++ 8 files changed, 756 insertions(+), 2 deletions(-) create mode 100644 examples/ng-file-upload.blade.php create mode 100644 src/Driver/NgFileUploadDriver.php create mode 100644 src/Range/NgFileUploadRange.php create mode 100644 tests/Driver/NgFileUploadDriverTest.php create mode 100644 tests/Range/NgFileUploadRangeTest.php diff --git a/README.md b/README.md index bb2d525..aa134d3 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ project at the moment is [tus](https://tus.io/). - [Blueimp](#blueimp-driver) - [DropzoneJS](#dropzonejs-driver) - [Flow.js](#flow-js-driver) + - [ng-file-upload](#ng-file-upload-driver) - [Resumable.js](#resumable-js-driver) - [simple-uploader.js](#simple-uploader-js-driver) - [Identifiers](#identifiers) @@ -152,6 +153,7 @@ Service | Driver name | Chunk [Blueimp](#blueimp-driver) | `blueimp` | yes | yes [DropzoneJS](#dropzonejs-driver) | `dropzone` | yes | no [Flow.js](#flow-js-driver) | `flow-js` | yes | yes +[ng-file-upload](#ng-file-upload-driver) | `ng-file-upload` | yes | no [Resumable.js](#resumable-js-driver) | `resumable-js` | yes | yes [simple-uploader.js](#simple-uploader-js-driver) | `simple-uploader-js` | yes | yes @@ -177,6 +179,12 @@ This driver handles requests made by the DropzoneJS client library. This driver handles requests made by the Flow.js client library. +### ng-file-upload driver + +[website](https://github.com/danialfarid/ng-file-upload) + +This driver handles requests made by the ng-file-upload client library. + ### Resumable.js driver [website](http://resumablejs.com/) diff --git a/config/chunk-uploader.php b/config/chunk-uploader.php index 8ebc04c..27ee52a 100644 --- a/config/chunk-uploader.php +++ b/config/chunk-uploader.php @@ -12,8 +12,8 @@ | throughout your application here. By default, the module is setup for | monolith upload. | - | Supported: "monolith", "blueimp", "dropzone", "flow-js", "resumable-js", - | "simple-uploader-js" + | Supported: "monolith", "blueimp", "dropzone", "flow-js", + | "ng-file-upload", "resumable-js", "simple-uploader-js" | */ diff --git a/examples/ng-file-upload.blade.php b/examples/ng-file-upload.blade.php new file mode 100644 index 0000000..a047e55 --- /dev/null +++ b/examples/ng-file-upload.blade.php @@ -0,0 +1,49 @@ + + + + + + + ng-file-upload + + +

ng-file-upload

+ +
+
+ +
+ + + Upload Successful +
+
+ + + + + + diff --git a/src/Driver/NgFileUploadDriver.php b/src/Driver/NgFileUploadDriver.php new file mode 100644 index 0000000..b58fec7 --- /dev/null +++ b/src/Driver/NgFileUploadDriver.php @@ -0,0 +1,174 @@ +identifier = $identifier; + } + + /** + * @inheritDoc + */ + public function handle(Request $request, StorageConfig $config, Closure $fileUploaded = null): Response + { + if ($this->isRequestMethodIn($request, [Request::METHOD_GET])) { + return $this->resume($request, $config); + } + + if ($this->isRequestMethodIn($request, [Request::METHOD_POST])) { + return $this->save($request, $config, $fileUploaded); + } + + throw new MethodNotAllowedHttpException([ + Request::METHOD_GET, + Request::METHOD_POST, + ]); + } + + private function resume(Request $request, StorageConfig $config): Response + { + $request->validate([ + 'file' => 'required', + 'totalSize' => 'required', + ]); + + $originalFilename = $request->get('file'); + $totalSize = $request->get('totalSize'); + $uuid = $this->identifier->generateFileIdentifier($totalSize, $originalFilename); + + if (!$this->chunkExists($config, $uuid)) { + return new JsonResponse([ + 'file' => $originalFilename, + 'size' => 0, + ]); + } + + $chunk = Arr::last($this->chunks($config, $uuid)); + $size = explode('-', basename($chunk))[1] + 1; + + return new JsonResponse([ + 'file' => $originalFilename, + 'size' => $size, + ]); + } + + private function save(Request $request, StorageConfig $config, Closure $fileUploaded = null): Response + { + $file = $request->file('file'); + + $this->validateUploadedFile($file); + + if ($this->isMonolithRequest($request)) { + return $this->saveMonolith($file, $config, $fileUploaded); + } + + $this->validateChunkRequest($request); + + return $this->saveChunk($file, $request, $config, $fileUploaded); + } + + private function isMonolithRequest(Request $request) + { + return empty($request->post()); + } + + /** + * @param \Illuminate\Http\Request $request + */ + private function validateChunkRequest(Request $request): void + { + $request->validate([ + '_chunkNumber' => 'required|numeric', + '_chunkSize' => 'required|numeric', + '_totalSize' => 'required|numeric', + '_currentChunkSize' => 'required|numeric', + ]); + } + + /** + * @param \Illuminate\Http\UploadedFile $file + * @param \CodingSocks\ChunkUploader\StorageConfig $config + * @param \Closure|null $fileUploaded + * + * @return \Symfony\Component\HttpFoundation\Response + */ + private function saveMonolith(UploadedFile $file, StorageConfig $config, Closure $fileUploaded = null): Response + { + $path = $file->store($config->getMergedDirectory(), [ + 'disk' => $config->getDisk(), + ]); + + $this->triggerFileUploadedEvent($config->getDisk(), $path, $fileUploaded); + + return new PercentageJsonResponse(100); + } + + /** + * @param \Illuminate\Http\UploadedFile $file + * @param \Illuminate\Http\Request $request + * @param \CodingSocks\ChunkUploader\StorageConfig $config + * @param \Closure|null $fileUploaded + * + * @return \Symfony\Component\HttpFoundation\Response + */ + private function saveChunk(UploadedFile $file, Request $request, StorageConfig $config, Closure $fileUploaded = null): Response + { + try { + $range = new NgFileUploadRange($request); + } catch (InvalidArgumentException $e) { + throw new BadRequestHttpException($e->getMessage(), $e); + } + + $originalFilename = $file->getClientOriginalName(); + $totalSize = $request->get('_totalSize'); + $uuid = $this->identifier->generateFileIdentifier($totalSize, $originalFilename); + + $chunks = $this->storeChunk($config, $range, $file, $uuid); + + if (!$range->isLast()) { + return new PercentageJsonResponse($range->getPercentage()); + } + + $targetFilename = $file->hashName(); + + $path = $this->mergeChunks($config, $chunks, $targetFilename); + + if ($config->sweep()) { + $this->deleteChunkDirectory($config, $uuid); + } + + $this->triggerFileUploadedEvent($config->getDisk(), $path, $fileUploaded); + + return new PercentageJsonResponse(100); + } +} diff --git a/src/Range/NgFileUploadRange.php b/src/Range/NgFileUploadRange.php new file mode 100644 index 0000000..d3c3d50 --- /dev/null +++ b/src/Range/NgFileUploadRange.php @@ -0,0 +1,95 @@ +chunkNumber = (int) $request->get(self::$CHUNK_NUMBER_PARAMETER_NAME); + $this->chunkSize = (int) $request->get(self::$CHUNK_SIZE_PARAMETER_NAME); + $this->currentChunkSize = (int) $request->get(self::$CURRENT_CHUNK_SIZE_PARAMETER_NAME); + $this->totalSize = (double) $request->get(self::$TOTAL_SIZE_PARAMETER_NAME); + + if ($this->chunkNumber < 0) { + throw new InvalidArgumentException(sprintf('`%s` must be greater than or equal to zero', self::$CHUNK_NUMBER_PARAMETER_NAME)); + } + if ($this->chunkSize < 1) { + throw new InvalidArgumentException(sprintf('`%s` must be greater than zero', self::$CHUNK_SIZE_PARAMETER_NAME)); + } + if ($this->currentChunkSize < 1) { + throw new InvalidArgumentException(sprintf('`%s` must be greater than zero', self::$CURRENT_CHUNK_SIZE_PARAMETER_NAME)); + } + if ($this->totalSize < 1) { + throw new InvalidArgumentException(sprintf('`%s` must be greater than zero', self::$TOTAL_SIZE_PARAMETER_NAME)); + } + } + + /** + * {@inheritDoc} + */ + public function getStart(): float + { + return $this->chunkNumber * $this->chunkSize; + } + + /** + * {@inheritDoc} + */ + public function getEnd(): float + { + return $this->getStart() + $this->currentChunkSize - 1; + } + + /** + * {@inheritDoc} + */ + public function getTotal(): float + { + return $this->totalSize; + } + + /** + * {@inheritDoc} + */ + public function isFirst(): bool + { + return $this->chunkNumber === 0; + } + + /** + * {@inheritDoc} + */ + public function isLast(): bool + { + return $this->getEnd() === ($this->getTotal() - 1); + } + + /** + * @return float + */ + public function getPercentage(): float + { + return floor(($this->getEnd() + 1) / $this->getTotal() * 100); + } +} diff --git a/src/UploadManager.php b/src/UploadManager.php index b1ec436..245db5c 100644 --- a/src/UploadManager.php +++ b/src/UploadManager.php @@ -5,6 +5,7 @@ use CodingSocks\ChunkUploader\Driver\BlueimpUploadDriver; use CodingSocks\ChunkUploader\Driver\DropzoneUploadDriver; use CodingSocks\ChunkUploader\Driver\FlowJsUploadDriver; +use CodingSocks\ChunkUploader\Driver\NgFileUploadDriver; use CodingSocks\ChunkUploader\Driver\MonolithUploadDriver; use CodingSocks\ChunkUploader\Driver\ResumableJsUploadDriver; use CodingSocks\ChunkUploader\Driver\SimpleUploaderJsUploadDriver; @@ -35,6 +36,14 @@ public function createFlowJsDriver() return new FlowJsUploadDriver($this->app['config']['chunk-uploader.resumable-js']); } + public function createNgFileUploadDriver() + { + /** @var \Illuminate\Support\Manager $identityManager */ + $identityManager = $this->app['chunk-uploader.identity-manager']; + + return new NgFileUploadDriver($identityManager->driver()); + } + public function createResumableJsDriver() { return new ResumableJsUploadDriver($this->app['config']['chunk-uploader.resumable-js']); diff --git a/tests/Driver/NgFileUploadDriverTest.php b/tests/Driver/NgFileUploadDriverTest.php new file mode 100644 index 0000000..318627d --- /dev/null +++ b/tests/Driver/NgFileUploadDriverTest.php @@ -0,0 +1,291 @@ +app->make('config')->set('chunk-uploader.identifier', 'nop'); + $this->app->make('config')->set('chunk-uploader.uploader', 'ng-file-upload'); + $this->app->make('config')->set('chunk-uploader.sweep', false); + $this->handler = $this->app->make(UploadHandler::class); + + Storage::fake('local'); + Event::fake(); + } + + public function testDriverInstance() + { + $manager = $this->app->make('chunk-uploader.upload-manager'); + + $this->assertInstanceOf(NgFileUploadDriver::class, $manager->driver()); + } + + public function notAllowedRequestMethods() + { + return [ + 'HEAD' => [Request::METHOD_HEAD], + 'PUT' => [Request::METHOD_PUT], + 'PATCH' => [Request::METHOD_PATCH], + 'DELETE' => [Request::METHOD_DELETE], + 'PURGE' => [Request::METHOD_PURGE], + 'OPTIONS' => [Request::METHOD_OPTIONS], + 'TRACE' => [Request::METHOD_TRACE], + 'CONNECT' => [Request::METHOD_CONNECT], + ]; + } + + /** + * @dataProvider notAllowedRequestMethods + */ + public function testMethodNotAllowed($requestMethod) + { + $request = Request::create('', $requestMethod); + + $this->expectException(MethodNotAllowedHttpException::class); + + $this->createTestResponse($this->handler->handle($request)); + } + + public function testResumeWhenChunkDoesNotExists() + { + $request = Request::create('', Request::METHOD_GET, [ + 'file' => 'test.txt', + 'totalSize' => '200', + ]); + + $response = $this->createTestResponse($this->handler->handle($request)); + $response->assertSuccessful(); + $response->assertJson(['size' => 0]); + } + + public function testResume() + { + $this->createFakeLocalFile('chunks/200_test.txt', '000-099'); + + $request = Request::create('', Request::METHOD_GET, [ + 'file' => 'test.txt', + 'totalSize' => '200', + ]); + + $response = $this->createTestResponse($this->handler->handle($request)); + $response->assertSuccessful(); + $response->assertJson(['size' => 100]); + } + + public function testUploadWhenFileParameterIsEmpty() + { + $request = Request::create('', Request::METHOD_POST); + + $this->expectException(BadRequestHttpException::class); + + $this->handler->handle($request); + } + + public function testUploadWhenFileParameterIsInvalid() + { + $file = Mockery::mock(UploadedFile::class) + ->makePartial(); + $file->shouldReceive('isValid') + ->andReturn(false); + + $request = Request::create('', Request::METHOD_POST, [], [], [ + 'file' => $file, + ]); + + $this->expectException(InternalServerErrorHttpException::class); + + $this->handler->handle($request); + } + + public function testUploadMonolith() + { + $file = UploadedFile::fake()->create('test.txt', 100); + $request = Request::create('', Request::METHOD_POST, [], [], [ + 'file' => $file, + ]); + + $response = $this->createTestResponse($this->handler->handle($request)); + $response->assertSuccessful(); + $response->assertJson(['done' => 100]); + + Storage::disk('local')->assertExists($file->hashName('merged')); + + Event::assertDispatched(FileUploaded::class, function ($event) use ($file) { + return $event->file = $file->hashName('merged'); + }); + } + + public function testUploadMonolithWithCallback() + { + $file = UploadedFile::fake()->create('test.txt', 100); + $request = Request::create('', Request::METHOD_POST, [], [], [ + 'file' => $file, + ]); + + $callback = $this->createClosureMock( + $this->once(), + 'local', + $file->hashName('merged') + ); + + $this->handler->handle($request, $callback); + + Event::assertDispatched(FileUploaded::class, function ($event) use ($file) { + return $event->file = $file->hashName('merged'); + }); + } + + public function excludedPostParameterProvider() + { + return [ + '_chunkNumber' => ['_chunkNumber'], + '_chunkSize' => ['_chunkSize'], + '_totalSize' => ['_totalSize'], + '_currentChunkSize' => ['_currentChunkSize'], + ]; + } + + /** + * @dataProvider excludedPostParameterProvider + */ + public function testPostParameterValidation($exclude) + { + $arr = [ + '_chunkNumber' => 1, + '_chunkSize' => 100, + '_totalSize' => 200, + '_currentChunkSize' => 100, + ]; + + unset($arr[$exclude]); + + $request = Request::create('', Request::METHOD_POST, $arr, [], [ + 'file' => UploadedFile::fake() + ->create('test.txt', 100), + ]); + + $this->expectException(ValidationException::class); + + $this->handler->handle($request); + } + + public function testUploadFirstChunk() + { + $file = UploadedFile::fake()->create('test.txt', 100); + $request = Request::create('', Request::METHOD_POST, [ + '_chunkNumber' => 0, + '_chunkSize' => 100, + '_totalSize' => 200, + '_currentChunkSize' => 100, + ], [], [ + 'file' => $file, + ]); + + $response = $this->createTestResponse($this->handler->handle($request)); + $response->assertSuccessful(); + $response->assertJson(['done' => 50]); + + Storage::disk('local')->assertExists('chunks/200_test.txt/000-099'); + + Event::assertNotDispatched(FileUploaded::class, function ($event) use ($file) { + return $event->file = $file->hashName('merged'); + }); + } + + public function testUploadFirstChunkWithCallback() + { + $file = UploadedFile::fake()->create('test.txt', 100); + $request = Request::create('', Request::METHOD_POST, [ + '_chunkNumber' => 0, + '_chunkSize' => 100, + '_totalSize' => 200, + '_currentChunkSize' => 100, + ], [], [ + 'file' => $file, + ]); + + $callback = $this->createClosureMock($this->never()); + + $this->handler->handle($request, $callback); + + Event::assertNotDispatched(FileUploaded::class, function ($event) use ($file) { + return $event->file = $file->hashName('merged'); + }); + } + + public function testUploadLastChunk() + { + $this->createFakeLocalFile('chunks/200_test.txt', '000-099'); + + $file = UploadedFile::fake()->create('test.txt', 100); + $request = Request::create('', Request::METHOD_POST, [ + '_chunkNumber' => 1, + '_chunkSize' => 100, + '_totalSize' => 200, + '_currentChunkSize' => 100, + ], [], [ + 'file' => $file, + ]); + + $response = $this->createTestResponse($this->handler->handle($request)); + $response->assertSuccessful(); + $response->assertJson(['done' => 100]); + + Storage::disk('local')->assertExists('chunks/200_test.txt/100-199'); + Storage::disk('local')->assertExists($file->hashName('merged')); + + Event::assertDispatched(FileUploaded::class, function ($event) use ($file) { + return $event->file = $file->hashName('merged'); + }); + } + + public function testUploadLastChunkWithCallback() + { + $this->createFakeLocalFile('chunks/200_test.txt', '000-099'); + + $file = UploadedFile::fake()->create('test.txt', 100); + $request = Request::create('', Request::METHOD_POST, [ + '_chunkNumber' => 1, + '_chunkSize' => 100, + '_totalSize' => 200, + '_currentChunkSize' => 100, + ], [], [ + 'file' => $file, + ]); + + $callback = $this->createClosureMock( + $this->once(), + 'local', + $file->hashName('merged') + ); + + $this->handler->handle($request, $callback); + + Event::assertDispatched(FileUploaded::class, function ($event) use ($file) { + return $event->file = $file->hashName('merged'); + }); + } +} diff --git a/tests/Range/NgFileUploadRangeTest.php b/tests/Range/NgFileUploadRangeTest.php new file mode 100644 index 0000000..a67eec6 --- /dev/null +++ b/tests/Range/NgFileUploadRangeTest.php @@ -0,0 +1,128 @@ + [-1, 10, 10, 100, '`_chunkNumber` must be greater than or equal to zero'], + 'Chunk size less than one' => [0, 0, 10, 100, '`_chunkSize` must be greater than zero'], + 'Current chunk size less than one' => [0, 10, 0, 100, '`_currentChunkSize` must be greater than zero'], + 'Total size less than one' => [0, 10, 10, 0, '`_totalSize` must be greater than zero'], + ]; + } + + /** + * @dataProvider invalidArgumentProvider + * + * @param $chunkNumber + * @param $chunkSize + * @param $currentChunkSize + * @param $totalSize + * @param $expectedExceptionMessage + */ + public function testArgumentValidation($chunkNumber, $chunkSize, $currentChunkSize, $totalSize, $expectedExceptionMessage) + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage($expectedExceptionMessage); + + $this->createRequestBodyRange($chunkNumber, $chunkSize, $currentChunkSize, $totalSize); + } + + public function testIsFirst() + { + $range = $this->createRequestBodyRange(0, 10, 10, 30); + $this->assertTrue($range->isFirst()); + + $range = $this->createRequestBodyRange(1, 10, 10, 30); + $this->assertFalse($range->isFirst()); + } + + public function testIsLast() + { + $range = $this->createRequestBodyRange(2, 10, 10, 30); + $this->assertTrue($range->isLast()); + + $range = $this->createRequestBodyRange(1, 10, 10, 30); + $this->assertFalse($range->isLast()); + } + + public function testIsFirstAndIsLast() + { + $range = $this->createRequestBodyRange(0, 10, 10, 10); + $this->assertTrue($range->isLast()); + $this->assertTrue($range->isLast()); + } + + public function testGetTotal() + { + $range = $this->createRequestBodyRange(4, 10, 10, 190); + $this->assertEquals(190, $range->getTotal()); + } + + public function testGetStart() + { + $range = $this->createRequestBodyRange(4, 10, 10, 190); + $this->assertEquals(40, $range->getStart()); + } + + public function testGetEnd() + { + $range = $this->createRequestBodyRange(4, 10, 10, 190); + $this->assertEquals(49, $range->getEnd()); + } + + public function testGetPercentage() + { + $range = $this->createRequestBodyRange(4, 10, 10, 100); + $this->assertEquals(50, $range->getPercentage()); + + $range = $this->createRequestBodyRange(9, 10, 10, 100); + $this->assertEquals(100, $range->getPercentage()); + } + + public function testCreateFromRequest() + { + $request = new Request([], [ + '_chunkNumber' => (string) 5, + '_chunkSize' => (string) 10, + '_currentChunkSize' => (string) 10, + '_totalSize' => (string) 100, + ]); + + $range = new NgFileUploadRange($request); + + $this->assertEquals(50, $range->getStart()); + $this->assertEquals(59, $range->getEnd()); + $this->assertEquals(100, $range->getTotal()); + } + + /** + * @param int $chunkNumber + * @param int $chunkSize + * @param int $currentChunkSize + * @param float $totalSize + * + * @return \CodingSocks\ChunkUploader\Range\NgFileUploadRange + */ + private function createRequestBodyRange(int $chunkNumber, int $chunkSize, int $currentChunkSize, float $totalSize) + { + $request = new ParameterBag([ + '_chunkNumber' => (string) $chunkNumber, + '_chunkSize' => (string) $chunkSize, + '_currentChunkSize' => (string) $currentChunkSize, + '_totalSize' => (string) $totalSize, + ]); + + return new NgFileUploadRange($request); + } +} From 3a01914d58d8bcd066e040129fb9bc3ad6e1ae35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20G=C3=B6r=C3=B6g?= Date: Sat, 20 Jun 2020 19:24:04 +0200 Subject: [PATCH 2/3] Re-arrange use --- src/Driver/NgFileUploadDriver.php | 10 +++++----- src/UploadManager.php | 2 +- tests/Range/NgFileUploadRangeTest.php | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Driver/NgFileUploadDriver.php b/src/Driver/NgFileUploadDriver.php index b58fec7..6f5ee66 100644 --- a/src/Driver/NgFileUploadDriver.php +++ b/src/Driver/NgFileUploadDriver.php @@ -3,16 +3,16 @@ namespace CodingSocks\ChunkUploader\Driver; use Closure; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; -use Illuminate\Http\UploadedFile; -use Illuminate\Support\Arr; -use InvalidArgumentException; use CodingSocks\ChunkUploader\Helper\ChunkHelpers; use CodingSocks\ChunkUploader\Identifier\Identifier; use CodingSocks\ChunkUploader\Range\NgFileUploadRange; use CodingSocks\ChunkUploader\Response\PercentageJsonResponse; use CodingSocks\ChunkUploader\StorageConfig; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; +use Illuminate\Http\UploadedFile; +use Illuminate\Support\Arr; +use InvalidArgumentException; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; diff --git a/src/UploadManager.php b/src/UploadManager.php index 245db5c..128ff85 100644 --- a/src/UploadManager.php +++ b/src/UploadManager.php @@ -5,8 +5,8 @@ use CodingSocks\ChunkUploader\Driver\BlueimpUploadDriver; use CodingSocks\ChunkUploader\Driver\DropzoneUploadDriver; use CodingSocks\ChunkUploader\Driver\FlowJsUploadDriver; -use CodingSocks\ChunkUploader\Driver\NgFileUploadDriver; use CodingSocks\ChunkUploader\Driver\MonolithUploadDriver; +use CodingSocks\ChunkUploader\Driver\NgFileUploadDriver; use CodingSocks\ChunkUploader\Driver\ResumableJsUploadDriver; use CodingSocks\ChunkUploader\Driver\SimpleUploaderJsUploadDriver; use Illuminate\Support\Manager; diff --git a/tests/Range/NgFileUploadRangeTest.php b/tests/Range/NgFileUploadRangeTest.php index a67eec6..ad34af0 100644 --- a/tests/Range/NgFileUploadRangeTest.php +++ b/tests/Range/NgFileUploadRangeTest.php @@ -2,9 +2,9 @@ namespace CodingSocks\ChunkUploader\Tests\Range; +use CodingSocks\ChunkUploader\Range\NgFileUploadRange; use Illuminate\Http\Request; use InvalidArgumentException; -use CodingSocks\ChunkUploader\Range\NgFileUploadRange; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\ParameterBag; From da3d0e7dfb9cd08f897a22f912093a8aa7b70fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20G=C3=B6r=C3=B6g?= Date: Sat, 20 Jun 2020 19:24:49 +0200 Subject: [PATCH 3/3] Remove unnecessary line --- tests/Range/NgFileUploadRangeTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Range/NgFileUploadRangeTest.php b/tests/Range/NgFileUploadRangeTest.php index ad34af0..54e5a0a 100644 --- a/tests/Range/NgFileUploadRangeTest.php +++ b/tests/Range/NgFileUploadRangeTest.php @@ -10,7 +10,6 @@ class NgFileUploadRangeTest extends TestCase { - public function invalidArgumentProvider() { return [