diff --git a/.github/workflows/run-tests-with-coverage.yml b/.github/workflows/run-tests-with-coverage.yml new file mode 100644 index 0000000..47cc699 --- /dev/null +++ b/.github/workflows/run-tests-with-coverage.yml @@ -0,0 +1,26 @@ +name: Run tests with coverage + +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] + +jobs: + tests-with-coverage: + runs-on: ubuntu-latest + steps: + - uses: shivammathur/setup-php@v2 + with: + php-version: '7.3' + - uses: actions/checkout@v3 + - name: Install Dependencies + run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist + - name: Execute unit tests via PHPUnit with coverage + run: vendor/bin/phpunit --coverage-clover build/logs/clover.xml + - name: Upload coverage results to Coveralls + env: + COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + composer global require php-coveralls/php-coveralls + php-coveralls --coverage_clover=build/logs/clover.xml -v diff --git a/.gitignore b/.gitignore index 3c39fef..b6d6068 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,6 @@ bootstrap/cache/ # Rocketeer PHP task runner and deployment package. https://github.com/rocketeers/rocketeer .rocketeer/ -composer.lock \ No newline at end of file +composer.lock + +.phpunit.result.cache diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4be32fe --- /dev/null +++ b/Dockerfile @@ -0,0 +1,5 @@ +FROM webdevops/php-nginx-dev:7.3 + +RUN wget -O "/usr/local/bin/go-replace" "https://github.com/webdevops/goreplace/releases/download/1.1.2/gr-arm64-linux" \ + && chmod +x "/usr/local/bin/go-replace" \ + && "/usr/local/bin/go-replace" --version diff --git a/bootstrap/autoload.php b/bootstrap/autoload.php new file mode 100755 index 0000000..3830137 --- /dev/null +++ b/bootstrap/autoload.php @@ -0,0 +1,34 @@ +=7.1.0", + "php": ">=7.3.0", "laravel/framework": ">=5.3.0", "phpunit/phpunit": ">=7.0|<=10.0" }, + "require-dev": { + "orchestra/testbench": "^6.25", + "php-coveralls/php-coveralls": "^2.5" + }, "autoload": { "psr-4": { - "RonasIT\\Support\\AutoDoc\\": "src/" + "RonasIT\\Support\\AutoDoc\\": "src/", + "RonasIT\\Support\\Tests\\": "tests/", + "RonasIT\\Support\\Tests\\Support\\Traits\\": "tests/support/Traits" }, "exclude-from-classmap": [ "src/Tests/" diff --git a/config/auto-doc.php b/config/auto-doc.php index 1c38045..e4b9b7d 100644 --- a/config/auto-doc.php +++ b/config/auto-doc.php @@ -31,7 +31,7 @@ | | You can use your custom documentation view */ - 'description' => 'swagger-description', + 'description' => 'auto-doc::swagger-description', 'version' => '0.0.0', 'title' => 'Name of Your Application', 'termsOfService' => '', diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b33a639 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +version: '3' + +services: + nginx: + build: . + working_dir: /app + ports: + - 80:80 + - 443:443 + volumes: + - ./:/app diff --git a/phpunit.xml b/phpunit.xml new file mode 100755 index 0000000..288f36d --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,22 @@ + + + + + ./src + + + ./app/Http/routes.php + + + + + ./tests + + + + + + + + + diff --git a/readme.md b/readme.md index 10fe8df..6c75826 100644 --- a/readme.md +++ b/readme.md @@ -8,6 +8,9 @@ License

+[![Laravel Swagger](https://github.com/RonasIT/laravel-swagger/actions/workflows/laravel.yml/badge.svg?branch=master)](https://github.com/RonasIT/laravel-swagger/actions/workflows/laravel.yml) +[![Coverage Status](https://coveralls.io/repos/github/RonasIT/laravel-swagger/badge.svg?branch=master)](https://coveralls.io/github/RonasIT/laravel-swagger?branch=master) + ## Introduction This plugin is designed to generate documentation for your REST API during the diff --git a/src/Views/documentation.blade.php b/resources/views/documentation.blade.php similarity index 100% rename from src/Views/documentation.blade.php rename to resources/views/documentation.blade.php diff --git a/src/Views/swagger-description.blade.php b/resources/views/swagger-description.blade.php similarity index 100% rename from src/Views/swagger-description.blade.php rename to resources/views/swagger-description.blade.php diff --git a/src/Views/swagger/favicon-16x16.png b/resources/views/swagger/favicon-16x16.png similarity index 100% rename from src/Views/swagger/favicon-16x16.png rename to resources/views/swagger/favicon-16x16.png diff --git a/src/Views/swagger/favicon-32x32.png b/resources/views/swagger/favicon-32x32.png similarity index 100% rename from src/Views/swagger/favicon-32x32.png rename to resources/views/swagger/favicon-32x32.png diff --git a/src/Views/swagger/swagger-ui-bundle.js b/resources/views/swagger/swagger-ui-bundle.js similarity index 100% rename from src/Views/swagger/swagger-ui-bundle.js rename to resources/views/swagger/swagger-ui-bundle.js diff --git a/src/Views/swagger/swagger-ui-bundle.js.map b/resources/views/swagger/swagger-ui-bundle.js.map similarity index 100% rename from src/Views/swagger/swagger-ui-bundle.js.map rename to resources/views/swagger/swagger-ui-bundle.js.map diff --git a/src/Views/swagger/swagger-ui-standalone-preset.js b/resources/views/swagger/swagger-ui-standalone-preset.js similarity index 100% rename from src/Views/swagger/swagger-ui-standalone-preset.js rename to resources/views/swagger/swagger-ui-standalone-preset.js diff --git a/src/Views/swagger/swagger-ui-standalone-preset.js.map b/resources/views/swagger/swagger-ui-standalone-preset.js.map similarity index 100% rename from src/Views/swagger/swagger-ui-standalone-preset.js.map rename to resources/views/swagger/swagger-ui-standalone-preset.js.map diff --git a/src/Views/swagger/swagger-ui.css b/resources/views/swagger/swagger-ui.css similarity index 100% rename from src/Views/swagger/swagger-ui.css rename to resources/views/swagger/swagger-ui.css diff --git a/src/Views/swagger/swagger-ui.css.map b/resources/views/swagger/swagger-ui.css.map similarity index 100% rename from src/Views/swagger/swagger-ui.css.map rename to resources/views/swagger/swagger-ui.css.map diff --git a/src/Views/swagger/swagger-ui.js b/resources/views/swagger/swagger-ui.js similarity index 100% rename from src/Views/swagger/swagger-ui.js rename to resources/views/swagger/swagger-ui.js diff --git a/src/Views/swagger/swagger-ui.js.map b/resources/views/swagger/swagger-ui.js.map similarity index 100% rename from src/Views/swagger/swagger-ui.js.map rename to resources/views/swagger/swagger-ui.js.map diff --git a/src/AutoDocServiceProvider.php b/src/AutoDocServiceProvider.php index 4652cd2..bfc4622 100644 --- a/src/AutoDocServiceProvider.php +++ b/src/AutoDocServiceProvider.php @@ -9,12 +9,10 @@ class AutoDocServiceProvider extends ServiceProvider { public function boot() { - $this->publishes([ - __DIR__ . '/../config/auto-doc.php' => config_path('auto-doc.php'), - ], 'config'); + $this->mergeConfigFrom(__DIR__ . '/../config/auto-doc.php', 'auto-doc'); $this->publishes([ - __DIR__ . '/Views/swagger-description.blade.php' => resource_path('views/swagger-description.blade.php'), + __DIR__ . '/../resources/views/swagger-description.blade.php' => resource_path('views/swagger-description.blade.php'), ], 'view'); if (!$this->app->routesAreCached()) { @@ -25,7 +23,7 @@ public function boot() PushDocumentationCommand::class ]); - $this->loadViewsFrom(__DIR__ . '/Views', 'auto-doc'); + $this->loadViewsFrom(__DIR__ . '/../resources/views', 'auto-doc'); } public function register() diff --git a/src/Drivers/LocalDriver.php b/src/Drivers/LocalDriver.php index 06b65e3..6b56c00 100755 --- a/src/Drivers/LocalDriver.php +++ b/src/Drivers/LocalDriver.php @@ -2,7 +2,6 @@ namespace RonasIT\Support\AutoDoc\Drivers; -use stdClass; use Illuminate\Contracts\Filesystem\FileNotFoundException; use RonasIT\Support\AutoDoc\Interfaces\SwaggerDriverInterface; use RonasIT\Support\AutoDoc\Exceptions\MissedProductionFilePathException; diff --git a/src/Drivers/RemoteDriver.php b/src/Drivers/RemoteDriver.php index 836799f..abac160 100755 --- a/src/Drivers/RemoteDriver.php +++ b/src/Drivers/RemoteDriver.php @@ -2,7 +2,7 @@ namespace RonasIT\Support\AutoDoc\Drivers; -use stdClass; +use Illuminate\Contracts\Filesystem\FileNotFoundException; use RonasIT\Support\AutoDoc\Interfaces\SwaggerDriverInterface; class RemoteDriver implements SwaggerDriverInterface @@ -36,16 +36,9 @@ public function getTmpData() public function saveData() { - $curl = curl_init(); - - curl_setopt($curl, CURLOPT_URL, $this->getUrl()); - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($this->getTmpData())); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); - - curl_exec($curl); - curl_close($curl); + $this->makeHttpRequest('post', $this->getUrl(), $this->getTmpData(), [ + 'Content-Type: application/json' + ]); if (file_exists($this->tempFileName)) { unlink($this->tempFileName); @@ -54,9 +47,9 @@ public function saveData() public function getDocumentation(): array { - $content = file_get_contents($this->getUrl()); + list($content, $statusCode) = $this->makeHttpRequest('get', $this->getUrl()); - if (empty($content)) { + if (empty($content) || $statusCode !== 200) { throw new FileNotFoundException(); } @@ -67,4 +60,29 @@ protected function getUrl(): string { return "{$this->remoteUrl}/documentations/{$this->key}"; } + + /** + * @codeCoverageIgnore + */ + protected function makeHttpRequest($type, $url, $data = [], $headers = []) + { + $curl = curl_init(); + + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + + if ($type === 'post') { + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data)); + } + + $result = curl_exec($curl); + + $statusCode = curl_getinfo($curl, CURLINFO_RESPONSE_CODE); + + curl_close($curl); + + return [$result, $statusCode]; + } } diff --git a/src/Drivers/StorageDriver.php b/src/Drivers/StorageDriver.php index 015e5d8..015631d 100755 --- a/src/Drivers/StorageDriver.php +++ b/src/Drivers/StorageDriver.php @@ -2,7 +2,6 @@ namespace RonasIT\Support\AutoDoc\Drivers; -use stdClass; use Illuminate\Support\Facades\Storage; use Illuminate\Contracts\Filesystem\FileNotFoundException; use RonasIT\Support\AutoDoc\Interfaces\SwaggerDriverInterface; diff --git a/storage/.gitignore b/storage/.gitignore new file mode 100755 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/tests/LocalDriverTest.php b/tests/LocalDriverTest.php new file mode 100755 index 0000000..939d5df --- /dev/null +++ b/tests/LocalDriverTest.php @@ -0,0 +1,72 @@ +tmpData = $this->getJsonFixture('tmp_data'); + $this->productionFilePath = __DIR__ . '/../storage/documentation.json'; + + config(['auto-doc.drivers.local.production_path' => $this->productionFilePath]); + + $this->localDriverClass = new LocalDriver(); + } + + public function testCreateClassConfigEmpty() + { + $this->expectException(MissedProductionFilePathException::class); + + config(['auto-doc.drivers.local.production_path' => null]); + + new LocalDriver(); + } + + public function testGetAndSaveTmpData() + { + $this->localDriverClass->saveTmpData($this->tmpData); + + $this->assertEquals($this->tmpData, $this->localDriverClass->getTmpData()); + } + + public function testSaveData() + { + $this->localDriverClass->saveTmpData($this->tmpData); + + $this->localDriverClass->saveData(); + + $this->assertFileExists($this->productionFilePath); + $this->assertFileEquals($this->generateFixturePath('tmp_data_non_formatted.json'), $this->productionFilePath); + + $this->assertEquals([], $this->localDriverClass->getTmpData()); + } + + public function testGetDocumentation() + { + file_put_contents($this->productionFilePath, json_encode($this->tmpData)); + + $documentation = $this->localDriverClass->getDocumentation(); + + $this->assertEquals($this->getJsonFixture('tmp_data'), $documentation); + } + + public function testGetDocumentationFileNotExists() + { + $this->expectException(FileNotFoundException::class); + + config(['auto-doc.drivers.local.production_path' => 'not_exists_file']); + + (new LocalDriver())->getDocumentation(); + } +} diff --git a/tests/RemoteDriverTest.php b/tests/RemoteDriverTest.php new file mode 100755 index 0000000..3d000d6 --- /dev/null +++ b/tests/RemoteDriverTest.php @@ -0,0 +1,128 @@ +tmpData = $this->getJsonFixture('tmp_data'); + $this->tmpDocumentationFilePath = __DIR__ . '/../storage/temp_documentation.json'; + + $this->remoteDriverClass = new RemoteDriver(); + } + + public function testSaveTmpData() + { + $this->remoteDriverClass->saveTmpData($this->tmpData); + + $this->assertFileExists($this->tmpDocumentationFilePath); + $this->assertFileEquals($this->generateFixturePath('tmp_data_non_formatted.json'), $this->tmpDocumentationFilePath); + } + + public function testGetTmpData() + { + file_put_contents($this->tmpDocumentationFilePath, json_encode($this->tmpData)); + + $result = $this->remoteDriverClass->getTmpData(); + + $this->assertEquals($this->tmpData, $result); + } + + public function testGetTmpDataNoFile() + { + $result = $this->remoteDriverClass->getTmpData(); + + $this->assertNull($result); + } + + public function testSaveData() + { + config(['auto-doc.drivers.remote.key' => 'mocked_key']); + config(['auto-doc.drivers.remote.url' => 'mocked_url']); + + $mock = $this->mockClass(RemoteDriver::class, ['makeHttpRequest']); + + $mock + ->expects($this->once()) + ->method('makeHttpRequest') + ->with('post', 'mocked_url/documentations/mocked_key', $this->tmpData, [ + 'Content-Type: application/json' + ]) + ->willReturn(true); + + file_put_contents($this->tmpDocumentationFilePath, json_encode($this->tmpData)); + + $mock->saveData(); + + $this->assertFileDoesNotExist($this->tmpDocumentationFilePath); + } + + public function testSaveDataWithoutTmpFile() + { + config(['auto-doc.drivers.remote.key' => 'mocked_key']); + config(['auto-doc.drivers.remote.url' => 'mocked_url']); + + $mock = $this->mockClass(RemoteDriver::class, ['makeHttpRequest']); + + $mock + ->expects($this->once()) + ->method('makeHttpRequest') + ->with('post', 'mocked_url/documentations/mocked_key', null, [ + 'Content-Type: application/json' + ]) + ->willReturn(true); + + $mock->saveData(); + } + + public function testGetDocumentation() + { + config(['auto-doc.drivers.remote.key' => 'mocked_key']); + config(['auto-doc.drivers.remote.url' => 'mocked_url']); + + $mock = $this->mockClass(RemoteDriver::class, ['makeHttpRequest']); + + $mock + ->expects($this->once()) + ->method('makeHttpRequest') + ->with('get', 'mocked_url/documentations/mocked_key') + ->willReturn([$this->getFixture('tmp_data_non_formatted.json'), 200]); + + $documentation = $mock->getDocumentation(); + + $this->assertEquals($this->tmpData, $documentation); + } + + public function testGetDocumentationNoFile() + { + $this->expectException(FileNotFoundException::class); + + config(['auto-doc.drivers.remote.key' => 'mocked_key']); + config(['auto-doc.drivers.remote.url' => 'mocked_url']); + + $mock = $this->mockClass(RemoteDriver::class, ['makeHttpRequest']); + + $mock + ->expects($this->once()) + ->method('makeHttpRequest') + ->with('get', 'mocked_url/documentations/mocked_key') + ->willReturn(json_encode([['error' => 'Not found.'], 404])); + + $documentation = $mock->getDocumentation(); + + $this->assertEquals($this->tmpData, $documentation); + } +} diff --git a/tests/StorageDriverTest.php b/tests/StorageDriverTest.php new file mode 100755 index 0000000..898ffd0 --- /dev/null +++ b/tests/StorageDriverTest.php @@ -0,0 +1,65 @@ +tmpData = $this->getJsonFixture('tmp_data'); + $this->filePath = __DIR__ . '/storage/documentation.json'; + + config(['auto-doc.drivers.storage.disk' => 'testing']); + config(['auto-doc.drivers.storage.production_path' => $this->filePath]); + + $this->disk = Storage::fake('testing'); + + $this->storageDriverClass = new StorageDriver(); + } + + public function testGetAndSaveTmpData() + { + $this->storageDriverClass->saveTmpData($this->tmpData); + + $this->assertEquals($this->tmpData, $this->storageDriverClass->getTmpData()); + } + + public function testSaveData() + { + $this->storageDriverClass->saveTmpData($this->tmpData); + + $this->storageDriverClass->saveData(); + + $this->disk->assertExists($this->filePath); + $this->assertEquals($this->getFixture('tmp_data_non_formatted.json'), $this->disk->get($this->filePath)); + + $this->assertEquals([], $this->storageDriverClass->getTmpData()); + } + + public function testGetDocumentation() + { + $this->disk->put($this->filePath, $this->getFixture('tmp_data_non_formatted.json')); + + $documentation = $this->storageDriverClass->getDocumentation(); + + $this->assertEquals($this->getJsonFixture('tmp_data'), $documentation); + } + + public function testGetDocumentationFileNotExists() + { + $this->expectException(FileNotFoundException::class); + + $this->storageDriverClass->getDocumentation(); + } +} diff --git a/tests/SwaggerServiceTest.php b/tests/SwaggerServiceTest.php new file mode 100755 index 0000000..4b6a1d7 --- /dev/null +++ b/tests/SwaggerServiceTest.php @@ -0,0 +1,132 @@ + '1.0']); + + $this->expectException(LegacyConfigException::class); + + app(SwaggerService::class); + } + + public function testConstructorEmptyConfigVersion() + { + config(['auto-doc.config_version' => null]); + + $this->expectException(LegacyConfigException::class); + + app(SwaggerService::class); + } + + public function testConstructorDriverClassNotExists() + { + config(['auto-doc.drivers.local.class' => 'NotExistsClass']); + + $this->expectException(SwaggerDriverClassNotFoundException::class); + + app(SwaggerService::class); + } + + public function testConstructorDriverClassNotImplementsInterface() + { + config(['auto-doc.drivers.local.class' => TestCase::class]); + + $this->expectException(InvalidDriverClassException::class); + + app(SwaggerService::class); + } + + public function testAddData() + { + $this->mockDriverSaveTmpData($this->getJsonFixture('tmp_data_search_roles_request')); + + $service = app(SwaggerService::class); + + $request = $this->generateRequest('get', 'users/roles', [ + 'with' => ['users'] + ], [], [ + 'Content-type' => 'application/json' + ]); + + $response = new Response($this->getFixture('example_success_roles_response.json'), 200, [ + 'Content-type' => 'application/json', + 'authorization' => 'Bearer some_token' + ]); + + $service->addData($request, $response); + } + + public function testAddDataWithJWTSecurity() + { + config(['auto-doc.security' => 'jwt']); + + $this->mockDriverSaveTmpData($this->getJsonFixture('tmp_data_search_roles_request_jwt_security')); + + $service = app(SwaggerService::class); + + $request = $this->generateRequest('get', 'users/roles', [ + 'with' => ['users'] + ]); + + $response = new Response($this->getFixture('example_success_roles_response.json'), 200, [ + 'Content-type' => 'application/json', + 'authorization' => 'Bearer some_token' + ]); + + $service->addData($request, $response); + } + + public function testAddDataWithLaravelSecurity() + { + config(['auto-doc.security' => 'laravel']); + + $this->mockDriverSaveTmpData($this->getJsonFixture('tmp_data_search_roles_request_laravel_security')); + + $service = app(SwaggerService::class); + + $request = $this->generateRequest('get', 'users/roles', [ + 'with' => ['users'] + ]); + + $response = new Response($this->getFixture('example_success_roles_response.json'), 200, [ + 'Content-type' => 'application/json', + 'authorization' => 'Bearer some_token' + ]); + + $service->addData($request, $response); + } + + public function testAddDataWithPathParameters() + { + $this->mockDriverSaveTmpData($this->getJsonFixture('tmp_data_get_user_request')); + + $service = app(SwaggerService::class); + + $request = $this->generateRequest('get', 'users/{id}/assign-role/{role-id}', [ + 'with' => ['role'], + 'with_likes_count' => true + ], [ + 'id' => 1, + 'role-id' => 5 + ]); + + $response = new Response($this->getFixture('example_success_user_response.json'), 200, [ + 'Content-type' => 'application/json' + ]); + + $service->addData($request, $response); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100755 index 0000000..f78406e --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,88 @@ +clearDirectory(__DIR__ . '/../storage', ['.gitignore']); + } + + protected function getPackageProviders($app): array + { + return [ + AutoDocServiceProvider::class + ]; + } + + protected function defineEnvironment($app) + { + $app->setBasePath(__DIR__ . '/..'); + } + + protected function getJsonFixture($name) + { + return json_decode($this->getFixture("{$name}.json"), true); + } + + protected function getFixture($name) + { + return file_get_contents($this->generateFixturePath($name)); + } + + protected function generateFixturePath($name): string + { + $testClass = last(explode('\\', get_class($this))); + + return __DIR__ . "/fixtures/{$testClass}/{$name}"; + } + + protected function clearDirectory($dirPath, $exceptPaths = []) + { + $fileSystem = new Filesystem(); + + $files = $fileSystem->allFiles($dirPath); + + foreach ($files as $file) { + if (!in_array($file->getFilename(), $exceptPaths)) { + $fileSystem->delete($file->getRealPath()); + } + } + } + + protected function generateRequest($type, $uri, $data = [], $pathParams = [], $headers = []): Request + { + $realUri = $uri; + + foreach ($pathParams as $pathParam => $value) { + $realUri = str_replace($pathParam, $value, $uri); + } + + $symfonyRequest = SymfonyRequest::create( + $this->prepareUrlForRequest($realUri), + strtoupper($type), + $data, + [], + [], + $this->transformHeadersToServerVars($headers) + ); + + $request = Request::createFromBase($symfonyRequest); + + $request->setRouteResolver(function () use ($uri) { + return Route::get($uri); + }); + + return $request; + } +} diff --git a/tests/fixtures/LocalDriverTest/tmp_data.json b/tests/fixtures/LocalDriverTest/tmp_data.json new file mode 100644 index 0000000..4c350c0 --- /dev/null +++ b/tests/fixtures/LocalDriverTest/tmp_data.json @@ -0,0 +1,120 @@ +{ + "swagger": "2.0", + "host": "localhost", + "basePath": "\/", + "schemes": [], + "paths": { + "\/auth\/login": { + "post": { + "tags": [ + "auth" + ], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "$ref": "#\/definitions\/authloginObject" + } + } + ], + "responses": { + "200": { + "description": "Operation successfully done", + "schema": { + "example": { + "token": "some_token", + "user": { + "id": 2, + "email": "user@test.com", + "deleted_at": null, + "created_at": "2017-11-16 06:08:34", + "updated_at": "2018-01-01 00:00:00", + "role_id": 2, + "state": "confirmed", + "reset_password_hash": null, + "failed_auth_attempts": 0, + "last_auth_attempt": "2018-01-01 00:00:00", + "first_name": "user", + "last_name": null, + "set_password_hash_created_at": null, + "full_name": "user", + "new_email": "new_email_test2@test.com", + "is_email_verified": true, + "role": { + "id": 2, + "name": "client", + "created_at": null, + "updated_at": null, + "settable": true + } + }, + "ttl": 60, + "refresh_ttl": 20160 + } + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "example": { + "error": "You have entered an incorrect credentials." + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "example": { + "error": "The limit of failed authorization attempts has been reached. You can't login in next 50 minutes." + } + } + } + }, + "security": [], + "description": "", + "summary": "login" + } + } + }, + "definitions": { + "authloginObject": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "2" + }, + "password": { + "type": "string", + "description": "" + } + }, + "required": [ + "email", + "password" + ], + "example": { + "email": "admin@test.com", + "password": "123" + } + } + }, + "info": { + "description": "This is automatically collected documentation", + "version": "0.0.0", + "title": "Project Title", + "termsOfService": "", + "contact": { + "email": "your@email.com" + } + } +} diff --git a/tests/fixtures/LocalDriverTest/tmp_data_non_formatted.json b/tests/fixtures/LocalDriverTest/tmp_data_non_formatted.json new file mode 100644 index 0000000..3ac95f3 --- /dev/null +++ b/tests/fixtures/LocalDriverTest/tmp_data_non_formatted.json @@ -0,0 +1 @@ +{"swagger":"2.0","host":"localhost","basePath":"\/","schemes":[],"paths":{"\/auth\/login":{"post":{"tags":["auth"],"consumes":["application\/json"],"produces":["application\/json"],"parameters":[{"in":"body","name":"body","description":"","required":true,"schema":{"$ref":"#\/definitions\/authloginObject"}}],"responses":{"200":{"description":"Operation successfully done","schema":{"example":{"token":"some_token","user":{"id":2,"email":"user@test.com","deleted_at":null,"created_at":"2017-11-16 06:08:34","updated_at":"2018-01-01 00:00:00","role_id":2,"state":"confirmed","reset_password_hash":null,"failed_auth_attempts":0,"last_auth_attempt":"2018-01-01 00:00:00","first_name":"user","last_name":null,"set_password_hash_created_at":null,"full_name":"user","new_email":"new_email_test2@test.com","is_email_verified":true,"role":{"id":2,"name":"client","created_at":null,"updated_at":null,"settable":true}},"ttl":60,"refresh_ttl":20160}}},"401":{"description":"Unauthorized","schema":{"example":{"error":"You have entered an incorrect credentials."}}},"400":{"description":"Bad Request","schema":{"example":{"error":"The limit of failed authorization attempts has been reached. You can't login in next 50 minutes."}}}},"security":[],"description":"","summary":"login"}}},"definitions":{"authloginObject":{"type":"object","properties":{"email":{"type":"string","description":"2"},"password":{"type":"string","description":""}},"required":["email","password"],"example":{"email":"admin@test.com","password":"123"}}},"info":{"description":"This is automatically collected documentation","version":"0.0.0","title":"Project Title","termsOfService":"","contact":{"email":"your@email.com"}}} \ No newline at end of file diff --git a/tests/fixtures/RemoteDriverTest/tmp_data.json b/tests/fixtures/RemoteDriverTest/tmp_data.json new file mode 100644 index 0000000..4c350c0 --- /dev/null +++ b/tests/fixtures/RemoteDriverTest/tmp_data.json @@ -0,0 +1,120 @@ +{ + "swagger": "2.0", + "host": "localhost", + "basePath": "\/", + "schemes": [], + "paths": { + "\/auth\/login": { + "post": { + "tags": [ + "auth" + ], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "$ref": "#\/definitions\/authloginObject" + } + } + ], + "responses": { + "200": { + "description": "Operation successfully done", + "schema": { + "example": { + "token": "some_token", + "user": { + "id": 2, + "email": "user@test.com", + "deleted_at": null, + "created_at": "2017-11-16 06:08:34", + "updated_at": "2018-01-01 00:00:00", + "role_id": 2, + "state": "confirmed", + "reset_password_hash": null, + "failed_auth_attempts": 0, + "last_auth_attempt": "2018-01-01 00:00:00", + "first_name": "user", + "last_name": null, + "set_password_hash_created_at": null, + "full_name": "user", + "new_email": "new_email_test2@test.com", + "is_email_verified": true, + "role": { + "id": 2, + "name": "client", + "created_at": null, + "updated_at": null, + "settable": true + } + }, + "ttl": 60, + "refresh_ttl": 20160 + } + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "example": { + "error": "You have entered an incorrect credentials." + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "example": { + "error": "The limit of failed authorization attempts has been reached. You can't login in next 50 minutes." + } + } + } + }, + "security": [], + "description": "", + "summary": "login" + } + } + }, + "definitions": { + "authloginObject": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "2" + }, + "password": { + "type": "string", + "description": "" + } + }, + "required": [ + "email", + "password" + ], + "example": { + "email": "admin@test.com", + "password": "123" + } + } + }, + "info": { + "description": "This is automatically collected documentation", + "version": "0.0.0", + "title": "Project Title", + "termsOfService": "", + "contact": { + "email": "your@email.com" + } + } +} diff --git a/tests/fixtures/RemoteDriverTest/tmp_data_non_formatted.json b/tests/fixtures/RemoteDriverTest/tmp_data_non_formatted.json new file mode 100644 index 0000000..3ac95f3 --- /dev/null +++ b/tests/fixtures/RemoteDriverTest/tmp_data_non_formatted.json @@ -0,0 +1 @@ +{"swagger":"2.0","host":"localhost","basePath":"\/","schemes":[],"paths":{"\/auth\/login":{"post":{"tags":["auth"],"consumes":["application\/json"],"produces":["application\/json"],"parameters":[{"in":"body","name":"body","description":"","required":true,"schema":{"$ref":"#\/definitions\/authloginObject"}}],"responses":{"200":{"description":"Operation successfully done","schema":{"example":{"token":"some_token","user":{"id":2,"email":"user@test.com","deleted_at":null,"created_at":"2017-11-16 06:08:34","updated_at":"2018-01-01 00:00:00","role_id":2,"state":"confirmed","reset_password_hash":null,"failed_auth_attempts":0,"last_auth_attempt":"2018-01-01 00:00:00","first_name":"user","last_name":null,"set_password_hash_created_at":null,"full_name":"user","new_email":"new_email_test2@test.com","is_email_verified":true,"role":{"id":2,"name":"client","created_at":null,"updated_at":null,"settable":true}},"ttl":60,"refresh_ttl":20160}}},"401":{"description":"Unauthorized","schema":{"example":{"error":"You have entered an incorrect credentials."}}},"400":{"description":"Bad Request","schema":{"example":{"error":"The limit of failed authorization attempts has been reached. You can't login in next 50 minutes."}}}},"security":[],"description":"","summary":"login"}}},"definitions":{"authloginObject":{"type":"object","properties":{"email":{"type":"string","description":"2"},"password":{"type":"string","description":""}},"required":["email","password"],"example":{"email":"admin@test.com","password":"123"}}},"info":{"description":"This is automatically collected documentation","version":"0.0.0","title":"Project Title","termsOfService":"","contact":{"email":"your@email.com"}}} \ No newline at end of file diff --git a/tests/fixtures/StorageDriverTest/tmp_data.json b/tests/fixtures/StorageDriverTest/tmp_data.json new file mode 100644 index 0000000..4c350c0 --- /dev/null +++ b/tests/fixtures/StorageDriverTest/tmp_data.json @@ -0,0 +1,120 @@ +{ + "swagger": "2.0", + "host": "localhost", + "basePath": "\/", + "schemes": [], + "paths": { + "\/auth\/login": { + "post": { + "tags": [ + "auth" + ], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "$ref": "#\/definitions\/authloginObject" + } + } + ], + "responses": { + "200": { + "description": "Operation successfully done", + "schema": { + "example": { + "token": "some_token", + "user": { + "id": 2, + "email": "user@test.com", + "deleted_at": null, + "created_at": "2017-11-16 06:08:34", + "updated_at": "2018-01-01 00:00:00", + "role_id": 2, + "state": "confirmed", + "reset_password_hash": null, + "failed_auth_attempts": 0, + "last_auth_attempt": "2018-01-01 00:00:00", + "first_name": "user", + "last_name": null, + "set_password_hash_created_at": null, + "full_name": "user", + "new_email": "new_email_test2@test.com", + "is_email_verified": true, + "role": { + "id": 2, + "name": "client", + "created_at": null, + "updated_at": null, + "settable": true + } + }, + "ttl": 60, + "refresh_ttl": 20160 + } + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "example": { + "error": "You have entered an incorrect credentials." + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "example": { + "error": "The limit of failed authorization attempts has been reached. You can't login in next 50 minutes." + } + } + } + }, + "security": [], + "description": "", + "summary": "login" + } + } + }, + "definitions": { + "authloginObject": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "2" + }, + "password": { + "type": "string", + "description": "" + } + }, + "required": [ + "email", + "password" + ], + "example": { + "email": "admin@test.com", + "password": "123" + } + } + }, + "info": { + "description": "This is automatically collected documentation", + "version": "0.0.0", + "title": "Project Title", + "termsOfService": "", + "contact": { + "email": "your@email.com" + } + } +} diff --git a/tests/fixtures/StorageDriverTest/tmp_data_non_formatted.json b/tests/fixtures/StorageDriverTest/tmp_data_non_formatted.json new file mode 100644 index 0000000..3ac95f3 --- /dev/null +++ b/tests/fixtures/StorageDriverTest/tmp_data_non_formatted.json @@ -0,0 +1 @@ +{"swagger":"2.0","host":"localhost","basePath":"\/","schemes":[],"paths":{"\/auth\/login":{"post":{"tags":["auth"],"consumes":["application\/json"],"produces":["application\/json"],"parameters":[{"in":"body","name":"body","description":"","required":true,"schema":{"$ref":"#\/definitions\/authloginObject"}}],"responses":{"200":{"description":"Operation successfully done","schema":{"example":{"token":"some_token","user":{"id":2,"email":"user@test.com","deleted_at":null,"created_at":"2017-11-16 06:08:34","updated_at":"2018-01-01 00:00:00","role_id":2,"state":"confirmed","reset_password_hash":null,"failed_auth_attempts":0,"last_auth_attempt":"2018-01-01 00:00:00","first_name":"user","last_name":null,"set_password_hash_created_at":null,"full_name":"user","new_email":"new_email_test2@test.com","is_email_verified":true,"role":{"id":2,"name":"client","created_at":null,"updated_at":null,"settable":true}},"ttl":60,"refresh_ttl":20160}}},"401":{"description":"Unauthorized","schema":{"example":{"error":"You have entered an incorrect credentials."}}},"400":{"description":"Bad Request","schema":{"example":{"error":"The limit of failed authorization attempts has been reached. You can't login in next 50 minutes."}}}},"security":[],"description":"","summary":"login"}}},"definitions":{"authloginObject":{"type":"object","properties":{"email":{"type":"string","description":"2"},"password":{"type":"string","description":""}},"required":["email","password"],"example":{"email":"admin@test.com","password":"123"}}},"info":{"description":"This is automatically collected documentation","version":"0.0.0","title":"Project Title","termsOfService":"","contact":{"email":"your@email.com"}}} \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/example_success_roles_response.json b/tests/fixtures/SwaggerServiceTest/example_success_roles_response.json new file mode 100644 index 0000000..e0e3a59 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/example_success_roles_response.json @@ -0,0 +1,26 @@ +[ + { + "id": 1, + "name": "admin", + "users": [ + { + "id": 1, + "name": "admin" + } + ] + }, + { + "id": 2, + "name": "client", + "users": [ + { + "id": 2, + "name": "first_client" + }, + { + "id": 3, + "name": "second_client" + } + ] + } +] diff --git a/tests/fixtures/SwaggerServiceTest/example_success_user_response.json b/tests/fixtures/SwaggerServiceTest/example_success_user_response.json new file mode 100644 index 0000000..0a100bb --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/example_success_user_response.json @@ -0,0 +1,9 @@ +{ + "id": 2, + "name": "first_client", + "likes_count": 23, + "role": { + "id": 2, + "name": "client" + } +} diff --git a/tests/fixtures/SwaggerServiceTest/tmp_data_get_user_request.json b/tests/fixtures/SwaggerServiceTest/tmp_data_get_user_request.json new file mode 100644 index 0000000..f7726e1 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/tmp_data_get_user_request.json @@ -0,0 +1,63 @@ +{ + "swagger": "2.0", + "host": "localhost", + "basePath": "/", + "schemes": [], + "paths": { + "/users/{id}/assign-role/{role-id}": { + "get": { + "tags": [ + "users" + ], + "consumes": [], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "", + "required": true, + "type": "string" + }, + { + "in": "path", + "name": "role-id", + "description": "", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "example": { + "id": 2, + "name": "first_client", + "likes_count": 23, + "role": { + "id": 2, + "name": "client" + } + } + } + } + }, + "security": [], + "description": "" + } + } + }, + "definitions": {}, + "info": { + "description": "This is automatically collected documentation", + "version": "0.0.0", + "title": "Name of Your Application", + "termsOfService": "", + "contact": { + "email": "your@email.com" + } + } +} diff --git a/tests/fixtures/SwaggerServiceTest/tmp_data_search_roles_request.json b/tests/fixtures/SwaggerServiceTest/tmp_data_search_roles_request.json new file mode 100644 index 0000000..c8b44d8 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/tmp_data_search_roles_request.json @@ -0,0 +1,67 @@ +{ + "swagger": "2.0", + "host": "localhost", + "basePath": "/", + "schemes": [], + "paths": { + "/users/roles": { + "get": { + "tags": [ + "users" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "OK", + "schema": { + "example": [ + { + "id": 1, + "name": "admin", + "users": [ + { + "id": 1, + "name": "admin" + } + ] + }, + { + "id": 2, + "name": "client", + "users": [ + { + "id": 2, + "name": "first_client" + }, + { + "id": 3, + "name": "second_client" + } + ] + } + ] + } + } + }, + "security": [], + "description": "" + } + } + }, + "definitions": {}, + "info": { + "description": "This is automatically collected documentation", + "version": "0.0.0", + "title": "Name of Your Application", + "termsOfService": "", + "contact": { + "email": "your@email.com" + } + } +} diff --git a/tests/fixtures/SwaggerServiceTest/tmp_data_search_roles_request_jwt_security.json b/tests/fixtures/SwaggerServiceTest/tmp_data_search_roles_request_jwt_security.json new file mode 100644 index 0000000..29ca2f1 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/tmp_data_search_roles_request_jwt_security.json @@ -0,0 +1,72 @@ +{ + "swagger": "2.0", + "host": "localhost", + "basePath": "/", + "schemes": [], + "paths": { + "/users/roles": { + "get": { + "tags": [ + "users" + ], + "consumes": [], + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "OK", + "schema": { + "example": [ + { + "id": 1, + "name": "admin", + "users": [ + { + "id": 1, + "name": "admin" + } + ] + }, + { + "id": 2, + "name": "client", + "users": [ + { + "id": 2, + "name": "first_client" + }, + { + "id": 3, + "name": "second_client" + } + ] + } + ] + } + } + }, + "security": [], + "description": "" + } + } + }, + "definitions": {}, + "info": { + "description": "This is automatically collected documentation", + "version": "0.0.0", + "title": "Name of Your Application", + "termsOfService": "", + "contact": { + "email": "your@email.com" + } + }, + "securityDefinitions": { + "jwt": { + "type": "apiKey", + "name": "authorization", + "in": "header" + } + } +} diff --git a/tests/fixtures/SwaggerServiceTest/tmp_data_search_roles_request_laravel_security.json b/tests/fixtures/SwaggerServiceTest/tmp_data_search_roles_request_laravel_security.json new file mode 100644 index 0000000..ac7b70d --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/tmp_data_search_roles_request_laravel_security.json @@ -0,0 +1,72 @@ +{ + "swagger": "2.0", + "host": "localhost", + "basePath": "/", + "schemes": [], + "paths": { + "/users/roles": { + "get": { + "tags": [ + "users" + ], + "consumes": [], + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "OK", + "schema": { + "example": [ + { + "id": 1, + "name": "admin", + "users": [ + { + "id": 1, + "name": "admin" + } + ] + }, + { + "id": 2, + "name": "client", + "users": [ + { + "id": 2, + "name": "first_client" + }, + { + "id": 3, + "name": "second_client" + } + ] + } + ] + } + } + }, + "security": [], + "description": "" + } + } + }, + "definitions": {}, + "info": { + "description": "This is automatically collected documentation", + "version": "0.0.0", + "title": "Name of Your Application", + "termsOfService": "", + "contact": { + "email": "your@email.com" + } + }, + "securityDefinitions": { + "laravel": { + "type": "apiKey", + "name": "Cookie", + "in": "header" + } + } +} diff --git a/tests/support/Traits/MockTrait.php b/tests/support/Traits/MockTrait.php new file mode 100644 index 0000000..5d06368 --- /dev/null +++ b/tests/support/Traits/MockTrait.php @@ -0,0 +1,14 @@ +getMockBuilder($className) + ->onlyMethods($methods) + ->getMock(); + } +} diff --git a/tests/support/Traits/SwaggerServiceMockTrait.php b/tests/support/Traits/SwaggerServiceMockTrait.php new file mode 100644 index 0000000..8ec68bf --- /dev/null +++ b/tests/support/Traits/SwaggerServiceMockTrait.php @@ -0,0 +1,21 @@ +mockClass($driverClass, ['saveTmpData']); + + $firstCall = array_merge($expectedData, ['paths' => []]); + + $driver->expects($this->exactly(2))->method('saveTmpData')->withConsecutive([$firstCall], [$expectedData]); + + $this->app->instance($driverClass, $driver); + } +}