Skip to content

Commit

Permalink
Merge pull request #15 from AndreasElia/new/refactor
Browse files Browse the repository at this point in the history
Refactor Command/Start Tests
  • Loading branch information
andreaselia authored Feb 19, 2021
2 parents 246305c + 3c2b16f commit 1b4b5b5
Show file tree
Hide file tree
Showing 11 changed files with 238 additions and 29 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/vendor
composer.lock
.phpunit.result.cache
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ You can modify the `api-postman.php` config values:
- `structured` - If you want folders to be generated based on route names.
- `base_url` - The base URL for all of your endpoints.
- `auth_middleware` - The middleware which wraps your authenticated API routes.
- `headers` - The headers applied to all routes within the collection.
- `enable_formdata` - Determines whether or not form data should be handled.
- `formdata` - The key/values to requests for form data dummy information.

Expand Down
10 changes: 9 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
"AndreasElia\\PostmanGenerator\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"AndreasElia\\PostmanGenerator\\Tests\\": "tests"
}
},
"require": {
"php": "^7.4|^8.0",
"ext-json": "*",
Expand All @@ -38,5 +43,8 @@
}
},
"minimum-stability": "dev",
"prefer-stable": true
"prefer-stable": true,
"require-dev": {
"orchestra/testbench": "^6.12"
}
}
20 changes: 14 additions & 6 deletions config/api-postman.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,28 @@
return [

/*
* Structured.
* Base URL.
*
* If you want folders to be generated based on namespace.
* The base URL for all of your endpoints.
*/

'structured' => false,
'base_url' => env('APP_URL', 'http://localhost'),

/*
* Base URL.
* Collection filename.
*
* The base URL for all of your endpoints.
* The name for the collection file to be saved.
*/

'base_url' => env('APP_URL', 'http://localhost'),
'filename' => '{timestamp}_{app}_collection.json',

/*
* Structured.
*
* If you want folders to be generated based on namespace.
*/

'structured' => false,

/*
* Auth Middleware.
Expand Down
32 changes: 32 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="vendor/autoload.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
>
<coverage>
<include>
<directory suffix=".php">src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<php>
<env name="DB_CONNECTION" value="testing"/>
</php>
</phpunit>
57 changes: 36 additions & 21 deletions src/ExportPostman.php → src/Commands/ExportPostmanCommand.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
<?php

namespace AndreasElia\PostmanGenerator;
namespace AndreasElia\PostmanGenerator\Commands;

use Closure;
use Illuminate\Console\Command;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use ReflectionClass;
use ReflectionFunction;

class ExportPostman extends Command
class ExportPostmanCommand extends Command
{
/** @var string */
protected $signature = 'export:postman {--bearer= : The bearer token to use on your endpoints}';
Expand All @@ -28,34 +29,35 @@ class ExportPostman extends Command
/** @var array */
protected $config;

/** @var null */
protected $filename;

public function __construct(Router $router, Repository $config)
{
parent::__construct();

$this->router = $router;
$this->config = $config['api-postman'];
$this->filename = $this->formatFilename();
}

public function handle(): void
{
$bearer = $this->option('bearer') ?? false;

$filename = date('Y_m_d_His').'_postman';

$this->initStructure($filename);
$this->initStructure();

if ($bearer) {
if ($bearer = $this->option('bearer') ?? false) {
$this->structure['variable'][] = [
'key' => 'token',
'value' => $bearer,
];
}

foreach ($this->router->getRoutes() as $route) {
$middleware = $route->middleware();
$methods = collect($route->methods())->reject(fn ($method) => $method == 'HEAD');
$middleware = $route->gatherMiddleware();

foreach ($route->methods as $method) {
if ($method == 'HEAD' || empty($middleware) || $middleware[0] !== 'api') {
foreach ($methods as $method) {
if (empty($middleware) || ! in_array('api', $middleware)) {
continue;
}

Expand Down Expand Up @@ -95,9 +97,9 @@ public function handle(): void
];
}

$request = $this->makeItem($route, $method, $routeHeaders, $requestRules);
$request = $this->makeRequest($route, $method, $routeHeaders, $requestRules);

if ($this->config['structured']) {
if ($this->isStructured()) {
$routeNames = $route->action['as'] ?? null;

if (! $routeNames) {
Expand All @@ -114,23 +116,22 @@ public function handle(): void
return ! is_null($value) && $value !== '';
});

$destination = end($routeNames);

$this->ensurePath($this->structure, $routeNames, $request, $destination);
$this->buildTree($this->structure, $routeNames, $request);
} else {
$this->structure['item'][] = $request;
}
}
}

Storage::put($exportName = "$filename.json", json_encode($this->structure));
Storage::put($exportName = "postman/$this->filename", json_encode($this->structure));

$this->info("Postman Collection Exported: $exportName");
}

protected function ensurePath(array &$routes, array $segments, array $request, string $destination): void
protected function buildTree(array &$routes, array $segments, array $request): void
{
$parent = &$routes;
$destination = end($segments);

foreach ($segments as $segment) {
$matched = false;
Expand Down Expand Up @@ -165,7 +166,7 @@ protected function ensurePath(array &$routes, array $segments, array $request, s
}
}

public function makeItem($route, $method, $routeHeaders, $requestRules)
public function makeRequest($route, $method, $routeHeaders, $requestRules)
{
$data = [
'name' => $route->uri(),
Expand Down Expand Up @@ -199,7 +200,7 @@ public function makeItem($route, $method, $routeHeaders, $requestRules)
return $data;
}

protected function initStructure(string $filename): void
protected function initStructure(): void
{
$this->structure = [
'variable' => [
Expand All @@ -209,10 +210,24 @@ protected function initStructure(string $filename): void
],
],
'info' => [
'name' => $filename,
'name' => $this->filename,
'schema' => 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json',
],
'item' => [],
];
}

protected function formatFilename()
{
return str_replace(
['{timestamp}', '{app}'],
[date('Y_m_d_His'), Str::snake(config('app.name'))],
$this->config['filename']
);
}

protected function isStructured()
{
return $this->config['structured'];
}
}
3 changes: 2 additions & 1 deletion src/PostmanGeneratorServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace AndreasElia\PostmanGenerator;

use AndreasElia\PostmanGenerator\Commands\ExportPostmanCommand;
use Illuminate\Support\ServiceProvider;

class PostmanGeneratorServiceProvider extends ServiceProvider
Expand All @@ -19,7 +20,7 @@ public function boot()
], 'postman-config');
}

$this->commands(ExportPostman::class);
$this->commands(ExportPostmanCommand::class);
}

/**
Expand Down
92 changes: 92 additions & 0 deletions tests/Feature/ExportPostmanTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

namespace AndreasElia\PostmanGenerator\Tests\Feature;

use AndreasElia\PostmanGenerator\Tests\TestCase;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Storage;

class ExportPostmanTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();

config()->set('api-postman.filename', 'test.json');

Storage::disk()->deleteDirectory('postman');
}

public function test_standard_export_works()
{
$this->artisan('export:postman')->assertExitCode(0);

$collection = json_decode(Storage::get('postman/'.config('api-postman.filename')), true);

$routes = $this->app['router']->getRoutes();

$collectionItems = $collection['item'];

$this->assertCount(count($routes), $collectionItems);
foreach ($routes as $route) {
$collectionRoute = Arr::first($collectionItems, function ($item) use ($route) {
return $item['name'] == $route->uri();
});

$this->assertNotNull($collectionRoute);
$this->assertTrue(in_array($collectionRoute['request']['method'], $route->methods()));
}
}

public function test_bearer_export_works()
{
$this->artisan('export:postman --bearer=1234567890')->assertExitCode(0);

$collection = json_decode(Storage::get('postman/'.config('api-postman.filename')), true);

$routes = $this->app['router']->getRoutes();

$collectionVariables = $collection['variable'];

foreach ($collectionVariables as $variable) {
if ($variable['key'] != 'token') {
continue;
}

$this->assertEquals($variable['value'], '1234567890');
}

$this->assertCount(2, $collectionVariables);

$collectionItems = $collection['item'];

$this->assertCount(count($routes), $collectionItems);

foreach ($routes as $route) {
$collectionRoute = Arr::first($collectionItems, function ($item) use ($route) {
return $item['name'] == $route->uri();
});

$this->assertNotNull($collectionRoute);
$this->assertTrue(in_array($collectionRoute['request']['method'], $route->methods()));
}
}

public function test_structured_export_works()
{
config()->set('api-postman.structured', true);

$this->artisan('export:postman')
->assertExitCode(0);

$this->assertTrue(true);

$collection = json_decode(Storage::get('postman/'.config('api-postman.filename')), true);

$routes = $this->app['router']->getRoutes();

$collectionItems = $collection['item'];

$this->assertCount(count($routes), $collectionItems[0]['item']);
}
}
28 changes: 28 additions & 0 deletions tests/Fixtures/ExampleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace AndreasElia\PostmanGenerator\Tests\Fixtures;

use Illuminate\Routing\Controller;

class ExampleController extends Controller
{
public function index()
{
return 'index';
}

public function show()
{
return 'show';
}

public function store()
{
return 'store';
}

public function delete()
{
return 'delete';
}
}
Loading

0 comments on commit 1b4b5b5

Please sign in to comment.