Преглед изворни кода

Implemented overrides support for Postman collection

shalvah пре 4 година
родитељ
комит
1fd9df4e5b

+ 7 - 0
config/scribe.php

@@ -137,6 +137,13 @@ INTRO
          * https://schema.getpostman.com/json/collection/v2.0.0/docs/index.html
          */
         'auth' => null,
+
+        /*
+         * Manually override some generated content in the spec. Dot notation is supported.
+         */
+        'overrides' => [
+            // 'info.version' => '2.0.0',
+        ],
     ],
 
     /*

+ 2 - 2
src/Writing/PostmanCollectionWriter.php

@@ -43,7 +43,7 @@ class PostmanCollectionWriter
         $this->auth = config('scribe.postman.auth');
     }
 
-    public function makePostmanCollection()
+    public function generatePostmanCollection()
     {
         $collection = [
             'variables' => [],
@@ -66,7 +66,7 @@ class PostmanCollectionWriter
             $collection['auth'] = $this->auth;
         }
 
-        return json_encode($collection, JSON_PRETTY_PRINT);
+        return $collection;
     }
 
     protected function generateEndpointItem($route): array

+ 8 - 1
src/Writing/Writer.php

@@ -218,7 +218,14 @@ class Writer
             ['routeGroups' => $routes, 'baseUrl' => $this->postmanBaseUrl]
         );
 
-        return $writer->makePostmanCollection();
+        $collection = $writer->generatePostmanCollection();
+        $overrides = $this->config->get('postman.overrides');
+        if (count($overrides)) {
+            foreach ($overrides as $key => $value) {
+                data_set($collection, $key, $value);
+            }
+        }
+        return json_encode($collection, JSON_PRETTY_PRINT);
     }
 
     public function generateOpenAPISpec(Collection $groupedEndpoints)

+ 185 - 0
tests/Fixtures/collection-overridden.json

@@ -0,0 +1,185 @@
+{
+    "variables": [],
+    "info": {
+        "name": "Custom API",
+        "_postman_id": "",
+        "description": "",
+        "schema": "https:\/\/schema.getpostman.com\/json\/collection\/v2.0.0\/collection.json",
+        "version": "3.9.9"
+    },
+    "item": [
+        {
+            "name": "Group A",
+            "description": "",
+            "item": [
+                {
+                    "name": "Example title.",
+                    "request": {
+                        "url": {
+                            "protocol": "http",
+                            "host": "localhost",
+                            "path": "api\/withDescription",
+                            "query": [],
+                            "raw": "http:\/\/localhost\/api\/withDescription"
+                        },
+                        "method": "GET",
+                        "header": [
+                            {
+                                "key": "Content-Type",
+                                "value": "application\/json"
+                            },
+                            {
+                                "key": "Accept",
+                                "value": "application\/json"
+                            }
+                        ],
+                        "body": {
+                            "mode": "raw",
+                            "raw": "[]",
+                            "options": {
+                                "raw": {
+                                    "language": "json"
+                                }
+                            }
+                        },
+                        "description": "This will be the long description.\nIt can also be multiple lines long.",
+                        "response": []
+                    }
+                },
+                {
+                    "name": "api\/withResponseTag",
+                    "request": {
+                        "url": {
+                            "protocol": "http",
+                            "host": "localhost",
+                            "path": "api\/withResponseTag",
+                            "query": [],
+                            "raw": "http:\/\/localhost\/api\/withResponseTag"
+                        },
+                        "method": "GET",
+                        "header": [
+                            {
+                                "key": "Content-Type",
+                                "value": "application\/json"
+                            },
+                            {
+                                "key": "Accept",
+                                "value": "application\/json"
+                            }
+                        ],
+                        "body": {
+                            "mode": "raw",
+                            "raw": "[]",
+                            "options": {
+                                "raw": {
+                                    "language": "json"
+                                }
+                            }
+                        },
+                        "description": "",
+                        "response": []
+                    }
+                },
+                {
+                    "name": "Endpoint with body parameters.",
+                    "request": {
+                        "url": {
+                            "protocol": "http",
+                            "host": "localhost",
+                            "path": "api\/withBodyParameters",
+                            "query": [],
+                            "raw": "http:\/\/localhost\/api\/withBodyParameters"
+                        },
+                        "method": "POST",
+                        "header": [
+                            {
+                                "key": "Content-Type",
+                                "value": "application\/json"
+                            },
+                            {
+                                "key": "Accept",
+                                "value": "application\/json"
+                            }
+                        ],
+                        "body": {
+                            "mode": "raw",
+                            "raw": "{\n    \"user_id\": 9,\n    \"room_id\": \"consequatur\",\n    \"forever\": false,\n    \"another_one\": 11613.31890586,\n    \"yet_another_param\": {\n        \"name\": \"consequatur\"\n    },\n    \"even_more_param\": [\n        11613.31890586\n    ],\n    \"book\": {\n        \"name\": \"consequatur\",\n        \"author_id\": 17,\n        \"pages_count\": 17\n    },\n    \"ids\": [\n        17\n    ],\n    \"users\": [\n        {\n            \"first_name\": \"John\",\n            \"last_name\": \"Doe\"\n        }\n    ]\n}",
+                            "options": {
+                                "raw": {
+                                    "language": "json"
+                                }
+                            }
+                        },
+                        "description": "",
+                        "response": []
+                    }
+                },
+                {
+                    "name": "api\/withQueryParameters",
+                    "request": {
+                        "url": {
+                            "protocol": "http",
+                            "host": "localhost",
+                            "path": "api\/withQueryParameters",
+                            "query": [
+                                {
+                                    "key": "location_id",
+                                    "value": "consequatur",
+                                    "description": "The id of the location.",
+                                    "disabled": false
+                                },
+                                {
+                                    "key": "user_id",
+                                    "value": "me",
+                                    "description": "The id of the user.",
+                                    "disabled": false
+                                },
+                                {
+                                    "key": "page",
+                                    "value": "4",
+                                    "description": "The page number.",
+                                    "disabled": false
+                                },
+                                {
+                                    "key": "filters",
+                                    "value": "consequatur",
+                                    "description": "The filters.",
+                                    "disabled": false
+                                },
+                                {
+                                    "key": "url_encoded",
+                                    "value": "%2B+%5B%5D%26%3D",
+                                    "description": "Used for testing that URL parameters will be URL-encoded where needed.",
+                                    "disabled": false
+                                }
+                            ],
+                            "raw": "http:\/\/localhost\/api\/withQueryParameters?location_id=consequatur&user_id=me&page=4&filters=consequatur&url_encoded=%2B+%5B%5D%26%3D"
+                        },
+                        "method": "GET",
+                        "header": [
+                            {
+                                "key": "Content-Type",
+                                "value": "application\/json"
+                            },
+                            {
+                                "key": "Accept",
+                                "value": "application\/json"
+                            }
+                        ],
+                        "body": {
+                            "mode": "raw",
+                            "raw": "[]",
+                            "options": {
+                                "raw": {
+                                    "language": "json"
+                                }
+                            }
+                        },
+                        "description": "",
+                        "response": []
+                    }
+                }
+            ]
+        }
+    ]
+}

+ 24 - 0
tests/GenerateDocumentationTest.php

@@ -260,6 +260,30 @@ class GenerateDocumentationTest extends TestCase
         $this->assertEquals($fixtureCollection, $generatedCollection);
     }
 
+    /** @test */
+    public function can_override_fields_in_generated_postman_collection_file()
+    {
+        RouteFacade::get('/api/withDescription', [TestController::class, 'withEndpointDescription']);
+        RouteFacade::get('/api/withResponseTag', TestController::class . '@withResponseTag');
+        RouteFacade::post('/api/withBodyParameters', TestController::class . '@withBodyParameters');
+        RouteFacade::get('/api/withQueryParameters', TestController::class . '@withQueryParameters');
+
+        config(['scribe.faker_seed' => 1234]);
+        config(['scribe.postman.enabled' => true]);
+        config(['scribe.postman.overrides' => [
+            'info.version' => '3.9.9',
+            'info.name' => 'Custom API',
+        ]]);
+        config(['scribe.routes.0.match.prefixes' => ['api/*']]);
+
+        $this->artisan('scribe:generate');
+
+        $generatedCollection = json_decode(file_get_contents(__DIR__ . '/../public/docs/collection.json'), true);
+        $generatedCollection['info']['_postman_id'] = '';
+        $fixtureCollection = json_decode(file_get_contents(__DIR__ . '/Fixtures/collection-overridden.json'), true);
+        $this->assertEquals($fixtureCollection, $generatedCollection);
+    }
+
     /** @test */
     public function generated_openapi_spec_file_is_correct()
     {

+ 37 - 46
tests/Unit/PostmanCollectionWriterTest.php

@@ -9,14 +9,18 @@ use Orchestra\Testbench\TestCase;
 
 class PostmanCollectionWriterTest extends TestCase
 {
-    public function testNameIsPresentInCollection()
+    public function testCorrectStructureIsFollowed()
     {
         \Config::set('scribe.title', 'Test API');
+        \Config::set('scribe.postman', [
+            'description' => 'A fake description',
+        ]);
 
         $writer = new PostmanCollectionWriter(new Collection(), '');
-        $collection = $writer->makePostmanCollection();
+        $collection = $writer->generatePostmanCollection();
 
-        $this->assertSame('Test API', json_decode($collection)->info->name);
+        $this->assertSame('Test API', $collection['info']['name']);
+        $this->assertSame('A fake description', $collection['info']['description']);
     }
 
     public function testFallbackCollectionNameIsUsed()
@@ -24,29 +28,17 @@ class PostmanCollectionWriterTest extends TestCase
         \Config::set('app.name', 'Fake App');
 
         $writer = new PostmanCollectionWriter(new Collection(), '');
-        $collection = $writer->makePostmanCollection();
-
-        $this->assertSame('Fake App API', json_decode($collection)->info->name);
-    }
-
-    public function testDescriptionIsPresentInCollection()
-    {
-        \Config::set('scribe.postman', [
-            'description' => 'A fake description',
-        ]);
-
-        $writer = new PostmanCollectionWriter(new Collection(), '');
-        $collection = $writer->makePostmanCollection();
+        $collection = $writer->generatePostmanCollection();
 
-        $this->assertSame('A fake description', json_decode($collection)->info->description);
+        $this->assertSame('Fake App API', $collection['info']['name']);
     }
 
     public function testAuthIsNotIncludedWhenNull()
     {
         $writer = new PostmanCollectionWriter(new Collection(), '');
-        $collection = $writer->makePostmanCollection();
+        $collection = $writer->generatePostmanCollection();
 
-        $this->assertArrayNotHasKey('auth', json_decode($collection, true));
+        $this->assertArrayNotHasKey('auth', $collection);
     }
 
     public function testAuthIsIncludedVerbatim()
@@ -60,9 +52,9 @@ class PostmanCollectionWriterTest extends TestCase
         ]);
 
         $writer = new PostmanCollectionWriter(new Collection(), '');
-        $collection = $writer->makePostmanCollection();
+        $collection = $writer->generatePostmanCollection();
 
-        $this->assertSame($auth, json_decode($collection, true)['auth']);
+        $this->assertSame($auth, $collection['auth']);
     }
 
     public function testEndpointIsParsed()
@@ -75,7 +67,7 @@ class PostmanCollectionWriterTest extends TestCase
         $collection = $this->createMockRouteGroup([$route], 'Group');
 
         $writer = new PostmanCollectionWriter($collection, 'fake.localhost');
-        $collection = json_decode($writer->makePostmanCollection(), true);
+        $collection = $writer->generatePostmanCollection();
 
         $this->assertSame('Group', data_get($collection, 'item.0.name'), 'Group name exists');
 
@@ -96,7 +88,7 @@ class PostmanCollectionWriterTest extends TestCase
     {
         $collection = $this->createMockRouteGroup([$this->createMockRouteData('fake')]);
         $writer = new PostmanCollectionWriter($collection, 'https://fake.localhost');
-        $collection = json_decode($writer->makePostmanCollection(), true);
+        $collection = $writer->generatePostmanCollection();
 
         $this->assertSame('https', data_get($collection, 'item.0.item.0.request.url.protocol'));
     }
@@ -109,7 +101,7 @@ class PostmanCollectionWriterTest extends TestCase
 
         $collection = $this->createMockRouteGroup([$route], 'Group');
         $writer = new PostmanCollectionWriter($collection, 'fake.localhost');
-        $collection = json_decode($writer->makePostmanCollection(), true);
+        $collection = $writer->generatePostmanCollection();
 
         $this->assertContains([
             'key' => 'X-Fake',
@@ -117,33 +109,25 @@ class PostmanCollectionWriterTest extends TestCase
         ], data_get($collection, 'item.0.item.0.request.header'));
     }
 
-    public function testUrlParametersAreConverted()
-    {
-        $collection = $this->createMockRouteGroup([$this->createMockRouteData('fake/{param}')]);
-        $writer = new PostmanCollectionWriter($collection, 'fake.localhost');
-        $collection = json_decode($writer->makePostmanCollection(), true);
-
-        $item = data_get($collection, 'item.0.item.0');
-        $this->assertSame('fake/{param}', $item['name'], 'Name defaults to path');
-        $this->assertSame('fake/:param', data_get($item, 'request.url.path'), 'Path is converted');
-    }
-
-    public function testUrlParamsResolveTheirDocumentation()
+    /** @test */
+    public function url_parameters_are_represented_properly()
     {
         $fakeRoute = $this->createMockRouteData('fake/{param}');
-
         $fakeRoute['urlParameters'] = ['param' => [
             'description' => 'A test description for the test param',
             'required' => true,
             'value' => 'foobar',
         ]];
-
         $collection = $this->createMockRouteGroup([$fakeRoute]);
+
         $writer = new PostmanCollectionWriter($collection, 'fake.localhost');
-        $collection = json_decode($writer->makePostmanCollection(), true);
+        $collection = $writer->generatePostmanCollection();
 
-        $variableData = data_get($collection, 'item.0.item.0.request.url.variable');
+        $item = data_get($collection, 'item.0.item.0');
+        $this->assertSame('fake/{param}', $item['name'], 'Name defaults to URL path');
+        $this->assertSame('fake/:param', data_get($item, 'request.url.path'), 'Path is converted');
 
+        $variableData = data_get($collection, 'item.0.item.0.request.url.variable');
         $this->assertCount(1, $variableData);
         $this->assertEquals([
             'id' => 'param',
@@ -153,6 +137,7 @@ class PostmanCollectionWriterTest extends TestCase
         ], $variableData[0]);
     }
 
+    /** @test */
     public function testQueryParametersAreDocumented()
     {
         $fakeRoute = $this->createMockRouteData('fake/path');
@@ -173,7 +158,7 @@ class PostmanCollectionWriterTest extends TestCase
 
         $collection = $this->createMockRouteGroup([$fakeRoute]);
         $writer = new PostmanCollectionWriter($collection, 'fake.localhost');
-        $collection = json_decode($writer->makePostmanCollection(), true);
+        $collection = $writer->generatePostmanCollection();
 
         $variableData = data_get($collection, 'item.0.item.0.request.url.query');
 
@@ -204,7 +189,7 @@ class PostmanCollectionWriterTest extends TestCase
 
         $collection = $this->createMockRouteGroup([$fakeRoute]);
         $writer = new PostmanCollectionWriter($collection, 'fake.localhost');
-        $collection = json_decode($writer->makePostmanCollection(), true);
+        $collection = $writer->generatePostmanCollection();
 
         $variableData = data_get($collection, 'item.0.item.0.request.url.query');
 
@@ -230,7 +215,7 @@ class PostmanCollectionWriterTest extends TestCase
 
         $collection = $this->createMockRouteGroup([$fakeRoute]);
         $writer = new PostmanCollectionWriter($collection, 'fake.localhost');
-        $collection = json_decode($writer->makePostmanCollection(), true);
+        $collection = $writer->generatePostmanCollection();
 
         $variableData = data_get($collection, 'item.0.item.0.request.url.query');
 
@@ -262,7 +247,7 @@ class PostmanCollectionWriterTest extends TestCase
         $route['headers'] = $expectedRemovedHeaders;
         $collection = $this->createMockRouteGroup([$route], 'Group');
         $writer = new PostmanCollectionWriter($collection, 'fake.localhost');
-        $collection = json_decode($writer->makePostmanCollection(), true);
+        $collection = $writer->generatePostmanCollection();
 
         foreach ($expectedRemovedHeaders as $key => $value) {
             $this->assertNotContains(compact('key', 'value'), data_get($collection, 'item.0.item.0.request.header'));
@@ -296,7 +281,7 @@ class PostmanCollectionWriterTest extends TestCase
         $route['headers'] = ['X-Authorization' => 'Test'];
         $collection = $this->createMockRouteGroup([$route], 'Group');
         $writer = new PostmanCollectionWriter($collection, 'fake.localhost');
-        $collection = json_decode($writer->makePostmanCollection(), true);
+        $collection = $writer->generatePostmanCollection();
 
         $this->assertContains([
             'key' => 'X-Authorization',
@@ -314,9 +299,15 @@ class PostmanCollectionWriterTest extends TestCase
                 'groupDescription' => '',
                 'title' => $title,
             ],
-            'queryParameters' => [],
             'urlParameters' => [],
+            'cleanUrlParameters' => [],
+            'queryParameters' => [],
+            'cleanQueryParameters' => [],
+            'bodyParameters' => [],
             'cleanBodyParameters' => [],
+            'fileParameters' => [],
+            'responses' => [],
+            'responseFields' => [],
         ];
     }