diff --git a/.gitignore b/.gitignore index 3938932..44e965a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ index.php composer.lock /.idea .php_cs.cache +/build diff --git a/composer.json b/composer.json index d99cddf..fa033b1 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,7 @@ } ], "require": { + "php": ">=7.0", "guzzlehttp/guzzle": "~6.0", "tightenco/collect": "^5.2" }, @@ -18,7 +19,13 @@ "Kunnu\\Dropbox\\": "src/Dropbox" } }, + "autoload-dev": { + "psr-4": { + "Kunnu\\Dropbox\\Tests\\": "tests/" + } + }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^6.0", + "mikey179/vfsStream": "^1.6" } } diff --git a/src/Dropbox/Dropbox.php b/src/Dropbox/Dropbox.php index b017c38..748d351 100644 --- a/src/Dropbox/Dropbox.php +++ b/src/Dropbox/Dropbox.php @@ -2,7 +2,6 @@ namespace Kunnu\Dropbox; -use Kunnu\Dropbox\Models\DeletedMetadata; use Kunnu\Dropbox\Models\File; use Kunnu\Dropbox\Models\Account; use Kunnu\Dropbox\Models\Thumbnail; @@ -204,16 +203,16 @@ public function getPersistentDataStore() * @param string $path Path of the file or folder * @param array $params Additional Params * - * @return \Kunnu\Dropbox\Models\FileMetadata | \Kunnu\Dropbox\Models\FolderMetadata + * @return \Kunnu\Dropbox\Models\FileMetadata | \Kunnu\Dropbox\Models\FolderMetadata | \Kunnu\Dropbox\Models\DeletedMetadata * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_metadata * */ - public function getMetadata($path, array $params = []) + public function getMetadata(string $path = '', array $params = []) { //Root folder is unsupported - if ($path === '/') { + if ('/' === $path || '' === $path) { throw new DropboxClientException("Metadata for the root folder is unsupported."); } @@ -301,8 +300,6 @@ public function setAccessToken($accessToken) * @param DropboxResponse $response * * @return \Kunnu\Dropbox\Models\ModelInterface - * - * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException */ public function makeModelFromResponse(DropboxResponse $response) { @@ -327,7 +324,7 @@ public function makeModelFromResponse(DropboxResponse $response) * * @return \Kunnu\Dropbox\Models\MetadataCollection */ - public function listFolder($path = null, array $params = []) + public function listFolder(string $path = '', array $params = []) { //Specify the root folder as an //empty string rather than as "/" @@ -356,7 +353,7 @@ public function listFolder($path = null, array $params = []) * * @return \Kunnu\Dropbox\Models\MetadataCollection */ - public function listFolderContinue($cursor) + public function listFolderContinue(string $cursor) { $response = $this->postToAPI('/files/list_folder/continue', ['cursor' => $cursor]); @@ -377,7 +374,7 @@ public function listFolderContinue($cursor) * @link https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder-get_latest_cursor * */ - public function listFolderLatestCursor($path, array $params = []) + public function listFolderLatestCursor(string $path = '', array $params = []) { //Specify the root folder as an //empty string rather than as "/" @@ -414,7 +411,7 @@ public function listFolderLatestCursor($path, array $params = []) * * @return \Kunnu\Dropbox\Models\ModelCollection */ - public function listRevisions($path, array $params = []) + public function listRevisions(string $path, array $params = []) { //Set the Path $params['path'] = $path; @@ -450,7 +447,7 @@ public function listRevisions($path, array $params = []) * * @return \Kunnu\Dropbox\Models\SearchResults */ - public function search($path, $query, array $params = []) + public function search(string $path = '', $query, array $params = []) { //Specify the root folder as an //empty string rather than as "/" @@ -477,18 +474,11 @@ public function search($path, $query, array $params = []) * * @return \Kunnu\Dropbox\Models\FolderMetadata * - * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException - * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-create_folder * */ - public function createFolder($path, $autorename = false) + public function createFolder(string $path, $autorename = false) { - //Path cannot be null - if (is_null($path)) { - throw new DropboxClientException("Path cannot be null."); - } - //Create Folder $response = $this->postToAPI('/files/create_folder', ['path' => $path, 'autorename' => $autorename]); @@ -496,7 +486,7 @@ public function createFolder($path, $autorename = false) $body = $response->getDecodedBody(); //Make and Return the Model - return new FolderMetadata($body); + return new FolderMetadata($body['metadata']); } /** @@ -504,30 +494,18 @@ public function createFolder($path, $autorename = false) * * @param string $path Path to file/folder to delete * - * @return \Kunnu\Dropbox\Models\DeletedMetadata - * - * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException + * @return \Kunnu\Dropbox\Models\FileMetadata | \Kunnu\Dropbox\Models\FolderMetadata * - * @link https://www.dropbox.com/developers/documentation/http/documentation#files-delete + * @link https://www.dropbox.com/developers/documentation/http/documentation#files-delete_v2 * */ - public function delete($path) + public function delete(string $path) { - //Path cannot be null - if (is_null($path)) { - throw new DropboxClientException("Path cannot be null."); - } - //Delete $response = $this->postToAPI('/files/delete_v2', ['path' => $path]); - $body = $response->getDecodedBody(); - - //Response doesn't have Metadata - if (!isset($body['metadata']) || !is_array($body['metadata'])) { - throw new DropboxClientException("Invalid Response."); - } - return new DeletedMetadata($body['metadata']); + //Make and Return the Model + return $this->makeModelFromResponse($response); } /** @@ -536,20 +514,13 @@ public function delete($path) * @param string $fromPath Path to be moved * @param string $toPath Path to be moved to * - * @return \Kunnu\Dropbox\Models\DeletedMetadata|\Kunnu\Dropbox\Models\FileMetadata - * - * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException + * @return \Kunnu\Dropbox\Models\FileMetadata | \Kunnu\Dropbox\Models\FolderMetadata * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-move * */ - public function move($fromPath, $toPath) + public function move(string $fromPath, string $toPath) { - //From and To paths cannot be null - if (is_null($fromPath) || is_null($toPath)) { - throw new DropboxClientException("From and To paths cannot be null."); - } - //Response $response = $this->postToAPI('/files/move', ['from_path' => $fromPath, 'to_path' => $toPath]); @@ -563,20 +534,13 @@ public function move($fromPath, $toPath) * @param string $fromPath Path to be copied * @param string $toPath Path to be copied to * - * @return \Kunnu\Dropbox\Models\DeletedMetadata|\Kunnu\Dropbox\Models\FileMetadata - * - * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException + * @return \Kunnu\Dropbox\Models\FileMetadata | \Kunnu\Dropbox\Models\FolderMetadata * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-copy * */ - public function copy($fromPath, $toPath) + public function copy(string $fromPath, string $toPath) { - //From and To paths cannot be null - if (is_null($fromPath) || is_null($toPath)) { - throw new DropboxClientException("From and To paths cannot be null."); - } - //Response $response = $this->postToAPI('/files/copy', ['from_path' => $fromPath, 'to_path' => $toPath]); @@ -590,20 +554,13 @@ public function copy($fromPath, $toPath) * @param string $path Path to the file to restore * @param string $rev Revision to store for the file * - * @return \Kunnu\Dropbox\Models\DeletedMetadata|\Kunnu\Dropbox\Models\FileMetadata|\Kunnu\Dropbox\Models\FolderMetadata - * - * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException + * @return \Kunnu\Dropbox\Models\FileMetadata * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-restore * */ - public function restore($path, $rev) + public function restore(string $path, string $rev) { - //Path and Revision cannot be null - if (is_null($path) || is_null($rev)) { - throw new DropboxClientException("Path and Revision cannot be null."); - } - //Response $response = $this->postToAPI('/files/restore', ['path' => $path, 'rev' => $rev]); @@ -621,18 +578,11 @@ public function restore($path, $rev) * * @return \Kunnu\Dropbox\Models\CopyReference * - * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException - * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-copy_reference-get * */ - public function getCopyReference($path) + public function getCopyReference(string $path) { - //Path cannot be null - if (is_null($path)) { - throw new DropboxClientException("Path cannot be null."); - } - //Get Copy Reference $response = $this->postToAPI('/files/copy_reference/get', ['path' => $path]); $body = $response->getDecodedBody(); @@ -654,13 +604,8 @@ public function getCopyReference($path) * @link https://www.dropbox.com/developers/documentation/http/documentation#files-copy_reference-save * */ - public function saveCopyReference($path, $copyReference) + public function saveCopyReference(string $path, string $copyReference) { - //Path and Copy Reference cannot be null - if (is_null($path) || is_null($copyReference)) { - throw new DropboxClientException("Path and Copy Reference cannot be null."); - } - //Save Copy Reference $response = $this->postToAPI('/files/copy_reference/save', ['path' => $path, 'copy_reference' => $copyReference]); $body = $response->getDecodedBody(); @@ -682,16 +627,9 @@ public function saveCopyReference($path, $copyReference) * https://www.dropbox.com/developers/documentation/http/documentation#files-get_temporary_link * * @return \Kunnu\Dropbox\Models\TemporaryLink - * - * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException */ - public function getTemporaryLink($path) + public function getTemporaryLink(string $path) { - //Path cannot be null - if (is_null($path)) { - throw new DropboxClientException("Path cannot be null."); - } - //Get Temporary Link $response = $this->postToAPI('/files/get_temporary_link', ['path' => $path]); @@ -712,13 +650,8 @@ public function getTemporaryLink($path) * @link https://www.dropbox.com/developers/documentation/http/documentation#files-save_url * */ - public function saveUrl($path, $url) + public function saveUrl(string $path, string $url) { - //Path and URL cannot be null - if (is_null($path) || is_null($url)) { - throw new DropboxClientException("Path and URL cannot be null."); - } - //Save URL $response = $this->postToAPI('/files/save_url', ['path' => $path, 'url' => $url]); $body = $response->getDecodedBody(); @@ -738,24 +671,17 @@ public function saveUrl($path, $url) * * @return \Kunnu\Dropbox\Models\FileMetadata|string Status (failed|in_progress) or FileMetadata (if complete) * - * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException - * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-save_url-check_job_status * */ - public function checkJobStatus($asyncJobId) + public function checkJobStatus(string $asyncJobId) { - //Async Job ID cannot be null - if (is_null($asyncJobId)) { - throw new DropboxClientException("Async Job ID cannot be null."); - } - //Get Job Status $response = $this->postToAPI('/files/save_url/check_job_status', ['async_job_id' => $asyncJobId]); $body = $response->getDecodedBody(); //Status - $status = isset($body['.tag']) ? $body['.tag'] : ''; + $status = $body['.tag'] ?? ''; //If status is complete if ($status === 'complete') { @@ -777,7 +703,7 @@ public function checkJobStatus($asyncJobId) * * @return \Kunnu\Dropbox\Models\FileMetadata */ - public function upload($dropboxFile, $path, array $params = []) + public function upload($dropboxFile, string $path, array $params = []) { //Make Dropbox File $dropboxFile = $this->makeDropboxFile($dropboxFile); @@ -918,6 +844,7 @@ public function startUploadSession($dropboxFile, $chunkSize = -1, $close = false //Upload File $file = $this->postToContent('/files/upload_session/start', $params); + $body = $file->getDecodedBody(); //Cannot retrieve Session ID @@ -955,21 +882,14 @@ public function postToContent($endpoint, array $params = [], $accessToken = null * * @return string Unique identifier for the upload session * - * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException - * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-append_v2 * */ - public function appendUploadSession($dropboxFile, $sessionId, $offset, $chunkSize, $close = false) + public function appendUploadSession($dropboxFile, string $sessionId, int $offset, int $chunkSize, bool $close = false) { //Make Dropbox File $dropboxFile = $this->makeDropboxFile($dropboxFile, $chunkSize, $offset); - //Session ID, offset, chunkSize and path cannot be null - if (is_null($sessionId) || is_null($offset) || is_null($chunkSize)) { - throw new DropboxClientException("Session ID, offset and chunk size cannot be null"); - } - $params = []; //Set the File @@ -1005,21 +925,14 @@ public function appendUploadSession($dropboxFile, $sessionId, $offset, $chunkSiz * * @return \Kunnu\Dropbox\Models\FileMetadata * - * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException - * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-finish * */ - public function finishUploadSession($dropboxFile, $sessionId, $offset, $remaining, $path, array $params = []) + public function finishUploadSession($dropboxFile, string $sessionId, int $offset, int $remaining, string $path, array $params = []) { //Make Dropbox File $dropboxFile = $this->makeDropboxFile($dropboxFile, $remaining, $offset); - //Session ID, offset, remaining and path cannot be null - if (is_null($sessionId) || is_null($path) || is_null($offset) || is_null($remaining)) { - throw new DropboxClientException("Session ID, offset, remaining and path cannot be null"); - } - $queryParams = []; //Set the File @@ -1083,13 +996,8 @@ public function simpleUpload($dropboxFile, $path, array $params = []) * @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_thumbnail * */ - public function getThumbnail($path, $size = 'small', $format = 'jpeg') + public function getThumbnail(string $path, $size = 'small', $format = 'jpeg') { - //Path cannot be null - if (is_null($path)) { - throw new DropboxClientException("Path cannot be null."); - } - //Invalid Format if (!in_array($format, ['jpeg', 'png'])) { throw new DropboxClientException("Invalid format. Must either be 'jpeg' or 'png'."); @@ -1175,18 +1083,11 @@ protected function getMetadataFromResponseHeaders(DropboxResponse $response) * * @return \Kunnu\Dropbox\Models\File * - * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException - * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-download * */ - public function download($path, $dropboxFile = null) + public function download(string $path, $dropboxFile = null) { - //Path cannot be null - if (is_null($path)) { - throw new DropboxClientException("Path cannot be null."); - } - //Make Dropbox File if target is specified $dropboxFile = $dropboxFile ? $this->makeDropboxFile($dropboxFile, null, null, DropboxFile::MODE_WRITE) : null; diff --git a/src/Dropbox/Models/ModelFactory.php b/src/Dropbox/Models/ModelFactory.php index 3c085cd..f8a8ca9 100644 --- a/src/Dropbox/Models/ModelFactory.php +++ b/src/Dropbox/Models/ModelFactory.php @@ -14,6 +14,12 @@ class ModelFactory */ public static function make(array $data = array()) { + //Some endpoints return metadata files or folder as sub-nodes of a `metadata` node + //i.e. /files/move_v2 + if (isset($data['metadata']['.tag'])) { + $data = $data['metadata']; + } + if (static::isFileOrFolder($data)) { $tag = $data['.tag']; @@ -26,6 +32,11 @@ public static function make(array $data = array()) if (static::isFolder($tag)) { return new FolderMetadata($data); } + + //Deleted File/Folder + if (static::isDeletedFileOrFolder($tag)) { + return new DeletedMetadata($data); + } } //Temporary Link @@ -43,11 +54,6 @@ public static function make(array $data = array()) return new SearchResults($data); } - //Deleted File/Folder - if (static::isDeletedFileOrFolder($data)) { - return new DeletedMetadata($data); - } - //Base Model return new BaseModel($data); } @@ -59,7 +65,7 @@ public static function make(array $data = array()) */ protected static function isFileOrFolder(array $data) { - return isset($data['.tag']) && isset($data['id']); + return isset($data['.tag']); } /** @@ -113,12 +119,12 @@ protected static function isSearchResult(array $data) } /** - * @param array $data + * @param string $tag * * @return bool */ - protected static function isDeletedFileOrFolder(array $data) + protected static function isDeletedFileOrFolder($tag) { - return !isset($data['.tag']) || !isset($data['id']); + return 'deleted' === $tag; } } diff --git a/tests/DropboxTest.php b/tests/DropboxTest.php index 2d77869..8e48ffa 100644 --- a/tests/DropboxTest.php +++ b/tests/DropboxTest.php @@ -1,10 +1,722 @@ + */ class DropboxTest extends TestCase { - public function testDemo() + use ResponsesTrait, DataProviderTrait, FilesystemMockTrait; + + public function testGetMetadataOnFile() + { + $dropbox = $this->getDropbox($this->getResponseFile()); + $metadata = $dropbox->getMetadata('/fake_dir/fake_file.txt'); + + $this->assertRequest('/files/get_metadata', ['path' => '/fake_dir/fake_file.txt']); + $this->assertInstanceOf(FileMetadata::class, $metadata); + $this->assertEquals('fake_file.txt', $metadata->getName()); + $this->assertEquals('/fake_dir/fake_file.txt', $metadata->getPathLower()); + $this->assertEquals('id:a4ayc_80_OEAAAAAAAAAXw', $metadata->getId()); + } + + public function testGetMetadataOnFolder() + { + $dropbox = $this->getDropbox($this->getResponseFolder()); + $metadata = $dropbox->getMetadata('/fake_dir'); + + $this->assertRequest('/files/get_metadata', ['path' => '/fake_dir']); + $this->assertInstanceOf(FolderMetadata::class, $metadata); + $this->assertEquals('fake_dir', $metadata->getName()); + $this->assertEquals('/fake_dir', $metadata->getPathLower()); + $this->assertEquals('id:g4p535ni2HABCDEFGHCQ', $metadata->getId()); + } + + public function testGetMetadataOnDeletedFile() + { + $dropbox = $this->getDropbox($this->getResponseDeleted()); + $metadata = $dropbox->getMetadata('/fake_dir/deleted_file.txt', ['include_deleted' => true]); + + $this->assertRequest('/files/get_metadata', ['include_deleted' => true, 'path' => '/fake_dir/deleted_file.txt']); + $this->assertInstanceOf(DeletedMetadata::class, $metadata); + $this->assertEquals('/fake_dir/deleted_file.txt', $metadata->getPathLower()); + } + + /** + * @expectedException \Kunnu\Dropbox\Exceptions\DropboxClientException + * @expectedExceptionMessage Metadata for the root folder is unsupported. + * + * @dataProvider providerRoots + * @param mixed $root + */ + public function testMetadataRootPathThrowsException($root) + { + $dropbox = $this->getDropbox(new Response409()); + $dropbox->getMetadata($root); + } + + /** + * @expectedException \Kunnu\Dropbox\Exceptions\DropboxClientException + */ + public function testGetMetadataErrorThrowsException() + { + $dropbox = $this->getDropbox($this->getResponseForMetadataError()); + $dropbox->getMetadata('/non_existent_path'); + } + + /** + * @dataProvider providerRoots + * @param mixed $root + */ + public function testListFolderRoot($root) + { + $dropbox = $this->getDropbox($this->getResponseForListRoot()); + $list = $dropbox->listFolder($root); + + $this->assertRequest('/files/list_folder', ['path' => '']); + $this->assertInstanceOf(MetadataCollection::class, $list); + $this->assertCount(4, $list->getItems()); + /** @var FolderMetadata $item */ + $item = $list->getItems()->first(); + $this->assertInstanceOf(FolderMetadata::class, $item); + $this->assertEquals("/photos", $item->getPathLower()); + $item = $list->getItems()[1]; + $this->assertInstanceOf(FolderMetadata::class, $item); + $this->assertEquals("/music", $item->getPathLower()); + $item = $list->getItems()[2]; + $this->assertInstanceOf(FileMetadata::class, $item); + $this->assertEquals("/getting started.pdf", $item->getPathLower()); + $item = $list->getItems()[3]; + $this->assertInstanceOf(FileMetadata::class, $item); + $this->assertEquals("/android intro.pdf", $item->getPathLower()); + } + + public function testListFolder() + { + $dropbox = $this->getDropbox($this->getResponseForList()); + $list = $dropbox->listFolder('/my_dir'); + + $this->assertRequest('/files/list_folder', ['path' => '/my_dir']); + + //Test response + $this->assertInstanceOf(MetadataCollection::class, $list); + $this->assertCount(2, $list->getItems()); + /** @var FolderMetadata $item */ + $item = $list->getItems()->first(); + $this->assertInstanceOf(FolderMetadata::class, $item); + $this->assertEquals("/my_dir/music", $item->getPathLower()); + $item = $list->getItems()[1]; + $this->assertInstanceOf(FileMetadata::class, $item); + $this->assertEquals("/my_dir/android intro.pdf", $item->getPathLower()); + } + + public function testMakeModelFromResponseNullBody() + { + $response = $this->createMock(DropboxResponse::class); + $response->method('getDecodedBody')->willReturn(null); + + $dropbox = new Dropbox($this->getApp()); + $model = $dropbox->makeModelFromResponse($response); + + $this->assertInstanceOf(BaseModel::class, $model); + $this->assertEquals([], $model->getData()); + } + + public function testListFolderContinue() + { + $dropbox = $this->getDropbox($this->getResponseForList()); + $list = $dropbox->listFolderContinue('fake_cursor'); + + $this->assertRequest('/files/list_folder/continue', ['cursor' => 'fake_cursor']); + $this->assertInstanceOf(MetadataCollection::class, $list); + $this->assertCount(2, $list->getItems()); + $this->assertEquals('fake_cursor', $list->getCursor()); + } + + public function testListFolderLatestCursor() + { + $dropbox = $this->getDropbox($this->getResponseCursor()); + $cursor = $dropbox->listFolderLatestCursor('/my/path'); + + $this->assertRequest('/files/list_folder/get_latest_cursor', ['path' => '/my/path']); + $this->assertEquals("ZtkX9_EHj3x7PMkVuFIhwKYXEpwpLwyxp9vMKomUhllil9q7eWiAu", $cursor); + } + + /** + * @dataProvider providerRoots + * @param mixed $root + */ + public function testListFolderLatestCursorRoot($root) + { + $dropbox = $this->getDropbox($this->getResponseCursor()); + $cursor = $dropbox->listFolderLatestCursor($root); + + $this->assertRequest('/files/list_folder/get_latest_cursor', ['path' => '']); + $this->assertEquals("ZtkX9_EHj3x7PMkVuFIhwKYXEpwpLwyxp9vMKomUhllil9q7eWiAu", $cursor); + } + + /** + * @expectedException \Kunnu\Dropbox\Exceptions\DropboxClientException + */ + public function testListFolderLatestCursorNoneThrowsException() + { + $dropbox = $this->getDropbox($this->getResponseFile()); + $dropbox->listFolderLatestCursor('/my/path'); + } + + public function testListRevisions() + { + $dropbox = $this->getDropbox($this->getResponseForListRevisions()); + $list = $dropbox->listRevisions('/myfile.txt'); + + $this->assertRequest('/files/list_revisions', ['path' => '/myfile.txt']); + $this->assertInstanceOf(ModelCollection::class, $list); + /** @var FileMetadata $rev */ + $rev = $list->first(); + $this->assertInstanceOf(FileMetadata::class, $rev); + $this->assertEquals('myfile.txt', $rev->getName()); + $this->assertEquals('35ef801f346f3', $rev->getRev()); + $rev1 = $list->get(1); + $this->assertInstanceOf(FileMetadata::class, $rev1); + $this->assertEquals('myfile.txt', $rev1->getName()); + $this->assertEquals('35dbe01f346f3', $rev1->getRev()); + } + + public function testSearch() + { + $dropbox = $this->getDropbox($this->getResponseForSearch()); + $results = $dropbox->search('/homework', 'prime numbers', ['mode' => 'filename']); + + $this->assertRequest('/files/search', ['mode' => 'filename', 'path' => '/homework', 'query' => 'prime numbers']); + $this->assertInstanceOf(SearchResults::class, $results); + $result = $results->getItems()->first(); + $this->assertInstanceOf(SearchResult::class, $result); + $this->assertEquals('/homework/math/prime_numbers.txt', $result->getMetadata()->getPathLower()); + } + + /** + * @dataProvider providerRoots + * @param mixed $root + */ + public function testSearchOnRoot($root) + { + $dropbox = $this->getDropbox($this->getResponseForSearch()); + $results = $dropbox->search($root, 'prime numbers'); + + $this->assertRequest('/files/search', ['path' => '', 'query' => 'prime numbers']); + $this->assertInstanceOf(SearchResults::class, $results); + $result = $results->getItems()->first(); + $this->assertInstanceOf(SearchResult::class, $result); + $this->assertEquals('/homework/math/prime_numbers.txt', $result->getMetadata()->getPathLower()); + } + + public function testCreateFolder() { - $this->assertEquals(0, 5 - 5); + $dropbox = $this->getDropbox($this->getResponseForCreateFolder()); + $folder = $dropbox->createFolder('/my_path'); + + $this->assertRequest('/files/create_folder', ['path' => '/my_path', 'autorename' => false]); + $this->assertInstanceOf(FolderMetadata::class, $folder); + $this->assertEquals('/my_path', $folder->getPathLower()); + } + + public function testDeleteFile() + { + $dropbox = $this->getDropbox($this->getResponseFile()); + $deleted = $dropbox->delete('/fake_dir/fake_file.txt'); + + $this->assertRequest('/files/delete_v2', ['path' => '/fake_dir/fake_file.txt']); + $this->assertInstanceOf(FileMetadata::class, $deleted); + $this->assertEquals("/FakeDir/FakeFile.txt", $deleted->getPathDisplay(), 'Name of deleted file.'); + } + + public function testDeleteFolder() + { + $dropbox = $this->getDropbox($this->getResponseFolder()); + $deleted = $dropbox->delete('/my_path'); + + $this->assertRequest('/files/delete_v2', ['path' => '/my_path']); + $this->assertInstanceOf(FolderMetadata::class, $deleted); + $this->assertEquals("/FakeDir", $deleted->getPathDisplay(), 'Name of deleted folder.'); + } + + public function testMoveFile() + { + $dropbox = $this->getDropbox($this->getResponseForMoveFile()); + $moved = $dropbox->move("/fake_dir/fake_file.txt", "/new_dir/fake_file.txt"); + + $this->assertRequest('/files/move', ['from_path' => '/fake_dir/fake_file.txt', 'to_path' => '/new_dir/fake_file.txt']); + $this->assertInstanceOf(FileMetadata::class, $moved); + $this->assertEquals("/new_dir/fake_file.txt", $moved->getPathLower()); + } + + public function testMoveFolder() + { + $dropbox = $this->getDropbox($this->getResponseForMoveFolder()); + $moved = $dropbox->move("/fake_dir", "/new_dir/fake_dir"); + + $this->assertRequest('/files/move', ['from_path' => '/fake_dir', 'to_path' => '/new_dir/fake_dir']); + $this->assertInstanceOf(FolderMetadata::class, $moved); + $this->assertEquals("/new_dir/fake_dir", $moved->getPathLower()); + } + + public function testCopyFile() + { + $dropbox = $this->getDropbox($this->getResponseFile()); + $file = $dropbox->copy('/fake_file.txt', '/fake_dir/fake_file.txt'); + + $this->assertRequest('/files/copy', ['from_path' => '/fake_file.txt', 'to_path' => '/fake_dir/fake_file.txt']); + $this->assertInstanceOf(FileMetadata::class, $file); + $this->assertEquals('/fake_dir/fake_file.txt', $file->getPathLower(), 'Correct file name'); + } + + public function testCopyFolder() + { + $dropbox = $this->getDropbox($this->getResponseFolder()); + $folder = $dropbox->copy('/new_dir/fake_dir', '/fake_dir'); + + $this->assertRequest('/files/copy', ['from_path' => '/new_dir/fake_dir', 'to_path' => '/fake_dir']); + $this->assertInstanceOf(FolderMetadata::class, $folder); + $this->assertEquals('/fake_dir', $folder->getPathLower(), 'Correct folder name'); + } + + public function testRestore() + { + $dropbox = $this->getDropbox($this->getResponseFile()); + $file = $dropbox->restore('/fake_dir/fake_file.txt', 'a1c10ce0dd78'); + $this->assertRequest('/files/restore', ['path' => '/fake_dir/fake_file.txt', 'rev' => 'a1c10ce0dd78']); + $this->assertInstanceOf(FileMetadata::class, $file); + $this->assertEquals('a1c10ce0dd78', $file->getRev()); + } + + public function testGetCopyReference() + { + $dropbox = $this->getDropbox($this->getResponseForGetCopyReferenceFile()); + $reference = $dropbox->getCopyReference('/my_dir/my_file.txt'); + + $this->assertRequest('/files/copy_reference/get', ['path' => '/my_dir/my_file.txt']); + $this->assertInstanceOf(CopyReference::class, $reference); + $this->assertEquals('AAAAAAHzRvNjM3RzazJvNnlxcjI', $reference->getReference(), 'Correct reference'); + $this->assertInstanceOf(FileMetadata::class, $reference->getMetadata()); + $this->assertEquals('id:gVmkYu1VfOEAAAAAAAABEA', $reference->getMetadata()->getId()); + } + + public function testGetCopyReferenceFolder() + { + $dropbox = $this->getDropbox($this->getResponseForGetCopyReferenceFolder()); + $reference = $dropbox->getCopyReference('/my_dir'); + + $this->assertRequest('/files/copy_reference/get', ['path' => '/my_dir']); + $this->assertInstanceOf(CopyReference::class, $reference); + $this->assertEquals('AAAAAAHzRvNrYXFtd3h4ZzE5ZjM', $reference->getReference(), 'Correct reference'); + $this->assertInstanceOf(FolderMetadata::class, $reference->getMetadata()); + $this->assertEquals('id:gVmkYu1VfOEAAAAAAAABEw', $reference->getMetadata()->getId()); + } + + public function testSaveCopyReference() + { + $dropbox = $this->getDropbox($this->getResponseForMoveFile()); + $reference = $dropbox->saveCopyReference('/new_dir/fake_file.txt', 'AAAAAAHzRvNjM3RzazJvNnlxcjI'); + + $this->assertRequest('/files/copy_reference/save', ['path' => '/new_dir/fake_file.txt', 'copy_reference' => 'AAAAAAHzRvNjM3RzazJvNnlxcjI']); + $this->assertInstanceOf(FileMetadata::class, $reference); + $this->assertEquals('id:a4ayc_80_OEAAAAAAAAAXw', $reference->getId()); + } + + public function testSaveCopyReferenceFolder() + { + $dropbox = $this->getDropbox($this->getResponseForMoveFolder()); + $reference = $dropbox->saveCopyReference('/new_dir/fake_dir', 'AAAAAAHzRvNrYXFtd3h4ZzE5ZjM'); + + $this->assertRequest('/files/copy_reference/save', ['path' => '/new_dir/fake_dir', 'copy_reference' => 'AAAAAAHzRvNrYXFtd3h4ZzE5ZjM']); + $this->assertInstanceOf(FolderMetadata::class, $reference); + $this->assertEquals('id:gVmkYu1VfOEAAAAAAAABEg', $reference->getId()); + } + + /** + * @expectedException \Kunnu\Dropbox\Exceptions\DropboxClientException + * @expectedExceptionMessage Invalid Response + * + * @dataProvider providerWrongResponse + * @param mixed $response + */ + public function testSaveCopyReferenceWrongResponseThrowsException($response) + { + $dropbox = $this->getDropbox($response); + $dropbox->saveCopyReference('/new_dir/fake_file.txt', 'AAAAAAHzRvNjM3RzazJvNnlxcjI'); + } + + public function testGetTemporaryLink() + { + $dropbox = $this->getDropbox($this->getResponseForGetTemporaryLink()); + $link = $dropbox->getTemporaryLink('/fake_dir/fake_file.txt'); + + $this->assertRequest('/files/get_temporary_link', ['path' => '/fake_dir/fake_file.txt']); + $this->assertInstanceOf(TemporaryLink::class, $link); + $this->assertEquals('https://fake.dropboxusercontent.com/fake_link', $link->getLink()); + + $file = $link->getMetadata(); + $this->assertInstanceOf(FileMetadata::class, $file); + $this->assertEquals('/fake_dir/fake_file.txt', $file->getPathLower()); + } + + public function testSaveUrl() + { + $dropbox = $this->getDropbox(new Response200("{\".tag\": \"async_job_id\", \"async_job_id\": \"fake_id\"}")); + $id = $dropbox->saveUrl('/fake_file.txt', 'http://www.example.com'); + + $this->assertRequest('/files/save_url', ['path' => '/fake_file.txt', 'url' => 'http://www.example.com']); + $this->assertEquals('fake_id', $id); + } + + public function testCheckJobStatusComplete() + { + $dropbox = $this->getDropbox($this->getResponseForCheckJobStatus()); + $complete = $dropbox->checkJobStatus('fake_id'); + + $this->assertRequest('/files/save_url/check_job_status', ['async_job_id' => 'fake_id']); + $this->assertInstanceOf(FileMetadata::class, $complete); + $this->assertEquals('/FakeFile.txt', $complete->getPathDisplay()); + } + + public function testCheckJobStatusFailed() + { + $dropbox = $this->getDropbox(new Response200('{".tag": "failed"}')); + $status = $dropbox->checkJobStatus('fake_id'); + + $this->assertRequest('/files/save_url/check_job_status', ['async_job_id' => 'fake_id']); + $this->assertEquals('failed', $status); + } + + /** + * @expectedException \Kunnu\Dropbox\Exceptions\DropboxClientException + * @expectedExceptionMessage Could not retrieve Async Job ID + */ + public function testSaveUrlWrongResponseThrowsException() + { + $dropbox = $this->getDropbox(new Response200('{"wrong_key": "wrong_value"}')); + $dropbox->saveUrl('/fake_file.txt', 'http://www.example.com'); + } + + public function testMakeDropboxFile() + { + $dropbox = new Dropbox($this->getApp()); + $file = $this->getFile(); + $dropboxFile = $dropbox->makeDropboxFile($file->url()); + $this->assertInstanceOf(DropboxFile::class, $dropboxFile); + $this->assertEquals($file->getContent(), $dropboxFile->getContents()); + $this->assertEquals($file->size(), $dropboxFile->getSize()); + $maxLength = new \ReflectionProperty(DropboxFile::class, 'maxLength'); + $maxLength->setAccessible(true); + $this->assertEquals(-1, $maxLength->getValue($dropboxFile)); + $offset = new \ReflectionProperty(DropboxFile::class, 'offset'); + $offset->setAccessible(true); + $this->assertEquals(-1, $offset->getValue($dropboxFile)); + } + + public function testMakeDropboxFileWithOptions() + { + $dropbox = new Dropbox($this->getApp()); + $file = $this->getFile(); + $dropboxFile = $dropbox->makeDropboxFile($file->url(), 10, 2); + $this->assertInstanceOf(DropboxFile::class, $dropboxFile); + $this->assertEquals(substr($file->getContent(), 2, 10), $dropboxFile->getContents(), 'Offset 2 byte and length 10 byte'); + $this->assertEquals($file->size(), $dropboxFile->getSize()); + $maxLength = new \ReflectionProperty(DropboxFile::class, 'maxLength'); + $maxLength->setAccessible(true); + $this->assertEquals(10, $maxLength->getValue($dropboxFile)); + $offset = new \ReflectionProperty(DropboxFile::class, 'offset'); + $offset->setAccessible(true); + $this->assertEquals(2, $offset->getValue($dropboxFile)); + } + + public function testMakeDropboxFileViaDropboxFile() + { + $dropbox = new Dropbox($this->getApp()); + $file = new DropboxFile($this->getFile()); + $dropboxFile = $dropbox->makeDropboxFile($file); + $this->assertSame($file, $dropboxFile, 'Return the same object'); + } + + public function testMakeDropboxFileDifferentMode() + { + $dropbox = new Dropbox($this->getApp()); + $file = new DropboxFile($this->getFile(), DropboxFile::MODE_WRITE); + $dropboxFile = $dropbox->makeDropboxFile($file); + $this->assertEquals(DropboxFile::MODE_READ, $dropboxFile->getMode(), 'Correct mode'); + $this->assertNotSame($file, $dropboxFile, 'Return a different object while mode is different'); + } + + public function testMakeDropboxFileLargeFiles() + { + $dropbox = new Dropbox($this->getApp()); + $file = $this->getLargeFile(); + $dropboxFile = $dropbox->makeDropboxFile($file->url()); + $this->assertInstanceOf(DropboxFile::class, $dropboxFile); + $this->assertEquals($file->size(), $dropboxFile->getSize()); + $this->assertEquals($file->read(100), $dropboxFile->getStream()->read(100)); + } + + public function testUpload() + { + $dropbox = $this->getDropbox($this->getResponseFile()); + $uploaded = $dropbox->upload($this->getFile()->url(), '/fake_dir/fake_file.txt', ['autorename' => 'true']); + + $this->assertRequest('/files/upload', ['autorename' => 'true', 'path' => '/fake_dir/fake_file.txt'], false); + + $this->assertInstanceOf(FileMetadata::class, $uploaded); + $this->assertEquals('/fake_dir/fake_file.txt', $uploaded->getPathLower()); + } + + public function testUploadDropboxFile() + { + $dropbox = $this->getDropbox($this->getResponseFile()); + $dropboxFile = new DropboxFile($this->getFile()->url()); + $uploaded = $dropbox->upload($dropboxFile, '/fake_dir/fake_file.txt', ['autorename' => 'true']); + + $this->assertRequest('/files/upload', ['autorename' => 'true', 'path' => '/fake_dir/fake_file.txt'], false); + $this->assertInstanceOf(FileMetadata::class, $uploaded); + $this->assertEquals('/fake_dir/fake_file.txt', $uploaded->getPathLower()); + } + + public function testStartUploadSession() + { + $file = $this->getLargeFile(1); + + $dropbox = $this->getDropbox($this->getResponseUploadSession()); + $sessionId = $dropbox->startUploadSession($file->url()); + + $this->assertRequest('/files/upload_session/start', ['close' => false], false); + $this->assertEquals('1234wxyz5678abcd', $sessionId); + } + + /** + * @expectedException \Kunnu\Dropbox\Exceptions\DropboxClientException + * @expectedExceptionMessage Could not retrieve Session ID + */ + public function testStartUploadSessionNoSessionIdThrowsException() + { + $file = $this->getFile(); + + $dropbox = $this->getDropbox($this->getResponseFile()); + $sessionId = $dropbox->startUploadSession($file->url()); + } + + public function testAppendUploadSession() + { + $file = $this->getFile(); + + $dropbox = $this->getDropbox(new Response200('')); + $sessionId = $dropbox->appendUploadSession($file->url(), 'fake_session_id', 0, 5); + $this->assertRequest('/files/upload_session/append_v2', [ + 'cursor' => ['session_id' => 'fake_session_id', 'offset' => 0], + 'close' => false + ], false); + $this->assertEquals('fake_session_id', $sessionId); + } + + public function testFinishUploadSession() + { + $file = $this->getFile(); + $dropbox = $this->getDropbox($this->getResponseFile()); + $metadata = $dropbox->finishUploadSession($file->url(), 'fake_session_id', 10, 20, '/fake_dir/fake_file.txt'); + + $this->assertRequest('/files/upload_session/finish', [ + 'cursor' => ['session_id' => 'fake_session_id', 'offset' => 10], + 'commit' => ['path' => '/fake_dir/fake_file.txt'] + ], false); + $this->assertInstanceOf(FileMetadata::class, $metadata); + $this->assertEquals('/fake_dir/fake_file.txt', $metadata->getPathLower()); + $this->assertEquals('id:a4ayc_80_OEAAAAAAAAAXw', $metadata->getId()); + } + + public function testUploadLargeFile() + { + $responses[] = $this->getResponseUploadSession(); + $responses[] = $this->getResponseFile(); + $responses[] = $this->getResponseFile(); + $options['http_client_handler'] = $this->getMockHandler($responses); + $dropbox = new Dropbox($this->getApp(), $options); + + $file = $this->getLargeFile(10); + $metadata = $dropbox->upload($file->url(), '/fake_dir/fake_file.txt'); + + //Test requests + $this->assertCount(3, $this->getHistory(), 'Two calls to Dropbox api'); + + /** @var Request $request */ + $request = $this->getHistory()[0]['request']; + $uri = $request->getUri(); + $this->assertEquals( + DropboxClient::CONTENT_PATH . '/files/upload_session/start', + "https://{$uri->getHost()}{$uri->getPath()}", + 'First call to upload_session/start endpoint' + ); + $this->assertEquals(['application/octet-stream'], $request->getHeader('Content-Type'), 'Stream content type'); + $this->assertEquals([json_encode(['close' => false])], $request->getHeader('Dropbox-API-Arg'), 'Correct Dropbox-API-Arg header'); + + /** @var Request $request */ + $request = $this->getHistory()[1]['request']; + $uri = $request->getUri(); + $this->assertEquals( + DropboxClient::CONTENT_PATH . '/files/upload_session/append_v2', + "https://{$uri->getHost()}{$uri->getPath()}", + 'Second call to upload_session/append endpoint' + ); + $this->assertEquals(['application/octet-stream'], $request->getHeader('Content-Type'), 'Stream content type'); + $responseBody = [ + 'cursor' => ['session_id' => '1234wxyz5678abcd', 'offset' => 4000000], + 'close' => false + ]; + $this->assertEquals([json_encode($responseBody)], $request->getHeader('Dropbox-API-Arg'), 'Correct Dropbox-API-Arg header'); + + /** @var Request $request */ + $request = $this->getHistory()[2]['request']; + $uri = $request->getUri(); + $this->assertEquals( + DropboxClient::CONTENT_PATH . '/files/upload_session/finish', + "https://{$uri->getHost()}{$uri->getPath()}", + 'Third call to upload_session/finish endpoint' + ); + $this->assertEquals(['application/octet-stream'], $request->getHeader('Content-Type'), 'Stream content type'); + $responseBody = [ + 'cursor' => ['session_id' => '1234wxyz5678abcd', 'offset' => 8000000], + 'commit' => ['path' => '/fake_dir/fake_file.txt'] + ]; + $this->assertEquals([json_encode($responseBody)], $request->getHeader('Dropbox-API-Arg'), 'Correct Dropbox-API-Arg header'); + + $this->assertInstanceOf(FileMetadata::class, $metadata); + $this->assertEquals('/fake_dir/fake_file.txt', $metadata->getPathLower()); + } + + public function testGetThumbnail() + { + $image = $this->getImage(); + $dropbox = $this->getDropbox($this->getResponseContentFile($image)); + $respFile = $dropbox->getThumbnail('/fake_dir/fake_image.jpg'); + $this->assertRequest('/files/get_thumbnail', [ + 'path' => '/fake_dir/fake_image.jpg', + 'format' => 'jpeg', + 'size' => 'w64h64' + ], false); + + $this->assertInstanceOf(Thumbnail::class, $respFile); + $this->assertEquals('/fake_dir/fake_image.jpg', $respFile->getMetadata()->getPathLower()); + $this->assertEquals($image->getContent(), $respFile->getContents()); + } + + /** + * @expectedException \Kunnu\Dropbox\Exceptions\DropboxClientException + * @expectedExceptionMessage Invalid format + */ + public function testGetThumbnailWrongFormatThrowsException() + { + $image = $this->getImage(); + $dropbox = $this->getDropbox($this->getResponseContentFile($image)); + $respFile = $dropbox->getThumbnail('/fake_dir/fake_image.jpg', 'small', 'tiff'); + } + + public function testDownload() + { + $file = $this->getImage(); + $dropbox = $this->getDropbox($this->getResponseContentFile($file)); + $downloaded = $dropbox->download('/fake_dir/fake_image.jpg'); + + $this->assertRequest('/files/download', ['path' => '/fake_dir/fake_image.jpg'], false); + $this->assertInstanceOf(File::class, $downloaded); + $this->assertEquals($file->getContent(), $downloaded->getContents()); + $this->assertEquals('/fake_dir/fake_image.jpg', $downloaded->getMetadata()->getPathLower()); + } + + public function testDownloadWithDefinedPath() + { + $file = $this->getImage(); + $dropbox = $this->getDropbox($this->getResponseContentFile($file)); + $outputFile = vfsStream::newFile('target_file.jpg')->at($this->getRoot()); + $downloaded = $dropbox->download('/fake_dir/fake_image.jpg', $outputFile->url()); + + $this->assertRequest('/files/download', ['path' => '/fake_dir/fake_image.jpg'], false); + $this->assertInstanceOf(File::class, $downloaded); + $this->assertEquals($file->getContent(), $downloaded->getContents()); + $this->assertEquals('/fake_dir/fake_image.jpg', $downloaded->getMetadata()->getPathLower()); + $this->assertEquals($file->getContent(), $outputFile->getContent()); + } + + public function testGetCurrentAccount() + { + $dropbox = $this->getDropbox($this->getResponseUser()); + $user = $dropbox->getCurrentAccount(); + + $this->assertRequest('/users/get_current_account', []); + $this->assertInstanceOf(Account::class, $user); + $this->assertEquals('fake_account_id', $user->getAccountId()); + } + + public function testGetAccount() + { + $dropbox = $this->getDropbox($this->getResponseUser()); + $user = $dropbox->getAccount('fake_account_id'); + + $this->assertRequest('/users/get_account', ['account_id' => 'fake_account_id']); + $this->assertInstanceOf(Account::class, $user); + $this->assertEquals('fake_account_id', $user->getAccountId()); + $this->assertEquals('Firstname Lastname', $user->getDisplayName()); + } + + public function testGetAccounts() + { + $dropbox = $this->getDropbox($this->getResponseUserList()); + $userList = $dropbox->getAccounts(['fake_account_id', 'fake_account_id_1']); + + $this->assertRequest('/users/get_account_batch', ['account_ids' => ['fake_account_id', 'fake_account_id_1']]); + $this->assertInstanceOf(AccountList::class, $userList); + + $this->assertEquals('fake_account_id', $userList[0]->getAccountId()); + $this->assertEquals('fake_account_id_1', $userList[1]->getAccountId()); + $this->assertEquals('Fake User', $userList[0]->getDisplayName()); + $this->assertEquals('Second Fake User', $userList[1]->getDisplayName()); + } + + public function testGetSpaceUsage() + { + $dropbox = $this->getDropbox($this->getResponseForSpaceUsage()); + $space = $dropbox->getSpaceUsage(); + + $this->assertRequest('/users/get_space_usage', []); + $expected = [ + 'used' => 2004434847, + 'allocation' => [ + '.tag' => 'individual', + 'allocated' => 7113539584 + ] + ]; + $this->assertEquals($expected, $space); } } diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..89a71fa --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,145 @@ + + */ +class TestCase extends BaseTestCase +{ + /** + * @var DropboxApp + */ + protected $app; + + /** + * @var callable + */ + protected $tracer; + + /** + * @var array + */ + protected $history; + + /** + * Set up the history middleware, to keep track of requests and responses. + * + * @see http://docs.guzzlephp.org/en/stable/testing.html + */ + public function setUp() + { + $this->history = []; + $this->tracer = Middleware::history($this->history); + } + + /** + * @return DropboxApp + */ + public function getApp() + { + if (null === $this->app) { + $this->app = new DropboxApp('fake_id', 'fake_secret', 'fake_token'); + } + + return $this->app; + } + + /** + * @return array + */ + public function getHistory() + { + return $this->history; + } + + /** + * Create a mock handler to test without a real call to Dropbox api. + * + * @param array $params An array of Response objects, expected to return from Dropbox api. + * + * @return DropboxHttpClientInterface + * + * @see http://docs.guzzlephp.org/en/stable/testing.html + */ + public function getMockHandler(array $params = []) + { + $mock = new MockHandler($params); + $handler = HandlerStack::create($mock); + $handler->push($this->tracer); + $client = new Client(['handler' => $handler]); + + return DropboxHttpClientFactory::make($client); + } + + /** + * Facility method to quickly retrieve an already mocked Dropbox instance. + * + * @param Response $response + * + * @return Dropbox + */ + public function getDropbox(Response $response) + { + $options['http_client_handler'] = $this->getMockHandler([$response]); + $dropbox = new Dropbox($this->getApp(), $options); + + return $dropbox; + } + + /** + * Facility method to perform standard assertions on requests: + * 1) single call to Dropbox api + * 2) POST method + * 3) correct uri + * 4) correct headers + * 5) correct request body. + * + * @param string $endpoint Url of the endpoint + * @param array $body The body of the request + * @param bool $rpc If it's an RPC endpoint + */ + public function assertRequest(string $endpoint, array $body, bool $rpc = true) + { + $path = $rpc ? DropboxClient::BASE_PATH : DropboxClient::CONTENT_PATH; + + //Test request + $this->assertCount(1, $this->getHistory(), 'One call to Dropbox api'); + /** @var Request $request */ + $request = $this->getHistory()[0]['request']; + $this->assertEquals('POST', $request->getMethod(), 'Submit Dropbox call via POST method'); + $this->assertEquals(['Bearer fake_token'], $request->getHeader('Authorization'), 'Authorization with token'); + $uri = $request->getUri(); + $this->assertEquals($path . $endpoint, "https://{$uri->getHost()}{$uri->getPath()}", 'Correct uri'); + + if ($rpc) { + if ('' === $bodyContents = $request->getBody()->getContents()) { + $this->assertEquals('', $request->getHeader('Content-Type')[0], 'Null content type when the body is empty'); + } else { + $this->assertEquals(['application/json'], $request->getHeader('Content-Type'), 'Json content type'); + $this->assertEquals(json_encode($body), $bodyContents, 'Correct request body'); + } + } else { + $expectedContent = ['application/octet-stream']; + if (in_array($uri->getPath(), ['/2/files/get_thumbnail', '/2/files/download'], true)) { + $expectedContent = ['']; + } + + $this->assertEquals($expectedContent, $request->getHeader('Content-Type'), 'Stream content type'); + $this->assertEquals([json_encode($body)], $request->getHeader('Dropbox-API-Arg'), 'Correct Dropbox-API-Arg header'); + } + } +} diff --git a/tests/Util/DataProviderTrait.php b/tests/Util/DataProviderTrait.php new file mode 100644 index 0000000..3998e7b --- /dev/null +++ b/tests/Util/DataProviderTrait.php @@ -0,0 +1,24 @@ + + */ +trait DataProviderTrait +{ + public function providerRoots() + { + return [['/'], ['']]; + } + + public function providerWrongResponse() + { + $response[] = [new Response200("{\".tag\": \"folder\", \"name\": \"fake_dir\", }")]; + $response[] = [new Response200("{\"metadata\": \"foo_bar\"}")]; + + return $response; + } +} diff --git a/tests/Util/FilesystemMockTrait.php b/tests/Util/FilesystemMockTrait.php new file mode 100644 index 0000000..42ff372 --- /dev/null +++ b/tests/Util/FilesystemMockTrait.php @@ -0,0 +1,106 @@ + + */ +trait FilesystemMockTrait +{ + /** + * @var vfsStreamDirectory + */ + protected $root; + + /** + * @var vfsStreamFile + */ + protected $file; + + /** + * @var vfsStreamFile + */ + protected $largeFile; + + /** + * @var vfsStreamFile + */ + protected $image; + + /** + * Return the root directory of a mocked filesystem. + * + * @return vfsStreamDirectory + */ + public function getRoot() + { + if (null === $this->root) { + $this->root = vfsStream::setup('fake_dir'); + } + + return $this->root; + } + + /** + * Return a mock file. + * + * @param string $filename + * + * @return vfsStreamFile + */ + public function getFile($filename = 'fake_file.txt') + { + if (null === $this->file) { + $this->file = vfsStream::newFile($filename) + ->withContent('Content of the fake file.') + ->at($this->getRoot()); + } + + return $this->file; + } + + /** + * Return a mock file, with given Mb size. + * + * @param string $filename + * @param int $size File size in Mb + * + * @return vfsStreamFile + */ + public function getLargeFile(int $size = 5, string $filename = 'fake_large_file.txt') + { + if (null === $this->largeFile) { + $this->largeFile = vfsStream::newFile($filename) + ->withContent(LargeFileContent::withMegabytes($size)) + ->at($this->getRoot()); + } + + return $this->largeFile; + } + + /** + * Return a mock jpeg file. + * + * @param string $name + * + * @throws \Exception + * @return vfsStreamFile + */ + public function getImage($name = 'fake_image.jpg') + { + if (null === $this->image) { + $this->image = vfsStream::newFile($name) + ->withContent(random_bytes(1024)) + ->at($this->getRoot()); + } + + return $this->image; + } +} diff --git a/tests/Util/Response200.php b/tests/Util/Response200.php new file mode 100644 index 0000000..d8489c6 --- /dev/null +++ b/tests/Util/Response200.php @@ -0,0 +1,20 @@ + 'application/json', + 'Authorization' => 'Bearer fake_token' + ]; + parent::__construct(200, $headers, $body); + } +} diff --git a/tests/Util/Response409.php b/tests/Util/Response409.php new file mode 100644 index 0000000..824e230 --- /dev/null +++ b/tests/Util/Response409.php @@ -0,0 +1,20 @@ + 'application/json', + 'Authorization' => 'Bearer fake_token' + ]; + parent::__construct(409, $headers, $body); + } +} diff --git a/tests/Util/ResponsesTrait.php b/tests/Util/ResponsesTrait.php new file mode 100644 index 0000000..ac6b567 --- /dev/null +++ b/tests/Util/ResponsesTrait.php @@ -0,0 +1,612 @@ + + */ +trait ResponsesTrait +{ + /** + * Return a response containing one file metadata. + * + * @return Response200 + */ + public function getResponseFile() + { + $body = << '', + 'Authorization' => 'Bearer fake_token', + 'dropbox-api-result' => json_encode([ + 'name'=> 'fake_image.jpg', + 'id'=> 'id:a4ayc_80_OEAAAAAAAAAXw', + 'client_modified'=> '2015-05-12T15:50:38Z', + 'server_modified'=> '2015-05-12T15:50:38Z', + 'rev'=> 'a1c10ce0dd78', + 'size'=> 1024, + 'path_lower'=> '/fake_dir/fake_image.jpg', + 'path_display'=> '/fake_dir/fake_image.jpg' + ]) + ]; + + return new Response(200, $headers, $file->getContent()); + } + + /** + * Response containing user information. + * + * @return Response200 + */ + public function getResponseUser() + { + $body = <<