diff --git a/composer.json b/composer.json index ecaf6538..5779e4d2 100644 --- a/composer.json +++ b/composer.json @@ -72,7 +72,8 @@ "extra": { "laravel": { "providers": [ - "Knuckles\\Scribe\\ScribeServiceProvider" + "Knuckles\\Scribe\\ScribeServiceProvider", + "Knuckles\\Scribe\\ScribeTestServiceProvider" ] } }, diff --git a/src/Exceptions/LaravelNotPresent.php b/src/Exceptions/LaravelNotPresent.php new file mode 100644 index 00000000..3ba11fff --- /dev/null +++ b/src/Exceptions/LaravelNotPresent.php @@ -0,0 +1,16 @@ +route)['method']; + // dd($methodDocBlock); + return $this->getHeadersFromDocBlock($methodDocBlock->getTags()); } diff --git a/src/Extracting/Strategies/Metadata/GetFromDocBlocksFromTest.php b/src/Extracting/Strategies/Metadata/GetFromDocBlocksFromTest.php new file mode 100644 index 00000000..a1e71b76 --- /dev/null +++ b/src/Extracting/Strategies/Metadata/GetFromDocBlocksFromTest.php @@ -0,0 +1,20 @@ +route); + $methodDocBlock = $docBlocks['method']; + $classDocBlock = $docBlocks['class']; + + return $this->getMetadataFromDocBlock($methodDocBlock, $classDocBlock); + } +} diff --git a/src/ScribeTestServiceProvider.php b/src/ScribeTestServiceProvider.php new file mode 100644 index 00000000..f72fad42 --- /dev/null +++ b/src/ScribeTestServiceProvider.php @@ -0,0 +1,27 @@ +app->environment('testing') && + $this->app->runningInConsole() && + config('scribe.generate_test_examples', true) + ) { + $this->registerMiddleware(); + } + } + + private function registerMiddleware(): void + { + $this->app[HttpKernel::class]->appendMiddlewareToGroup('web', HttpExampleCreatorMiddleware::class); + $this->app[HttpKernel::class]->appendMiddlewareToGroup('api', HttpExampleCreatorMiddleware::class); + } +} diff --git a/src/Tests/ExampleCreator.php b/src/Tests/ExampleCreator.php new file mode 100644 index 00000000..3fe2d221 --- /dev/null +++ b/src/Tests/ExampleCreator.php @@ -0,0 +1,156 @@ +setProps($props); + + $this->id = (string) Str::orderedUuid(); + + $this->testClass = get_class($this->test); + } + + public static function getCurrentInstance() + { + return static::$currentInstance; + } + + public static function setCurrentInstance($instance) + { + static::$currentInstance = $instance; + } + + public static function normalizeUriForInstanceKey(Route $route) + { + $parts = [ + str_replace('/', '~', $route->uri) + ]; + $parts = array_merge($parts, $route->methods); + + return implode(',', $parts); + } + + public static function getInstanceForRoute($route) + { + if ($instance = static::$instances[static::normalizeUriForInstanceKey($route)] ?? null) { + return $instance; + } + + $instance = static::getCurrentInstance()->setRoute($route); + + return static::registerInstance($instance); + } + + protected static function registerInstance($instance) + { + return static::$instances[$instance->instanceKey()] = $instance; + } + + public static function getInstances() + { + return static::$instances; + } + + public static function flushInstances() + { + static::$instances = []; + } + + public function addExampleRequest(ExampleRequest $exampleRequest) + { + $this->exampleRequests[] = $exampleRequest; + + return $this; + } + + public function setRoute(Route $route) + { + $this->route = $route; + + return $this; + } + + public function instanceKey() + { + return $this->normalizeUriForInstanceKey($this->route); + } + + public function writeDir() + { + return storage_path('scribe/'.$this->instanceKey()); + } + + public function toArray() + { + return [ + 'id' => $this->id, + 'test_class' => $this->testClass, + 'test_method' => $this->testMethod, + 'provided_data' => $this->providedData, + 'data_name' => $this->dataName, + 'key' => $this->instanceKey(), + 'route' => [ + 'uri' => $this->route->uri, + 'name' => $this->route->getName(), + 'methods' => $this->route->methods, + ], + ]; + } + + public function mergeParamsExample($type) + { + $method = 'get'.ucfirst($type).'ParamsExample'; + $results = []; + + foreach ($exampleRequests as $request) { + $results = array_merge($results, $request->{$method}()); + } + + return $results; + } + + public function writeExampleRequests() + { + return [ + 'urlParam' => [], + 'queryParam' => [], + 'bodyParam' => [], + 'responses' => [ + [ + 'status' => 200, + 'scenario' => 'test_user_should_return_user', + 'data' => [], + ], [ + 'status' => 404, + 'scenario' => 'test_user_not_found', + 'data' => [], + ], + ], + ]; + } +} diff --git a/src/Tests/ExampleRequest.php b/src/Tests/ExampleRequest.php new file mode 100644 index 00000000..07ae6eae --- /dev/null +++ b/src/Tests/ExampleRequest.php @@ -0,0 +1,39 @@ +id = (string) Str::orderedUuid(); + $this->request = $request; + $this->response = $response; + } + + public function getUrlParamsExample() + { + return []; + } + + public function getQueryParamsExample() + { + return []; + } + + public function getBodyParamsExample() + { + return $this->request->all(); + } + + public function getResponse() + { + return $this->response->getContent(); + } +} diff --git a/src/Tests/HttpExamples/HttpExampleCreatorMiddleware.php b/src/Tests/HttpExamples/HttpExampleCreatorMiddleware.php new file mode 100644 index 00000000..b1eb0258 --- /dev/null +++ b/src/Tests/HttpExamples/HttpExampleCreatorMiddleware.php @@ -0,0 +1,22 @@ +route()); + + $exampleCreator->addExampleRequest(new ExampleRequest($request, $response)); + + return $response; + } +} diff --git a/src/Tests/ScribeSetup.php b/src/Tests/ScribeSetup.php new file mode 100644 index 00000000..88daf102 --- /dev/null +++ b/src/Tests/ScribeSetup.php @@ -0,0 +1,44 @@ +app)) { + throw new LaravelNotPresent; + } + + if (config('scribe.generate_test_examples', true)) { + $this->afterApplicationCreated(function () { + dump('making example...'); + $this->makeExample(); + }); + + $this->beforeApplicationDestroyed(function () { + dump('writing examples...'); + $instances = ExampleCreator::getInstances(); + foreach ($instances as $instance) { + dump($instance->toArray()); + } + ExampleCreator::flushInstances(); + // $this->saveExampleStatus(); + }); + } + } + + private function makeExample(): void + { + $exampleCreator = new ExampleCreator([ + 'test' => $this, + 'testMethod' => $this->getName(false), + 'providedData' => $this->getProvidedData(), + 'dataName' => $this->dataName(), + ]); + + ExampleCreator::setCurrentInstance($exampleCreator); + } +} diff --git a/src/Tests/Traits/SetProps.php b/src/Tests/Traits/SetProps.php new file mode 100644 index 00000000..75398e41 --- /dev/null +++ b/src/Tests/Traits/SetProps.php @@ -0,0 +1,15 @@ + $value) { + $this->{$key} = $value; + } + + return $this; + } +}