Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ Syntax:

--only-resource : Set this flag if you want to create only resource.

--only-nova-resource : Set this flag if you want to create only nova resource.

--only-nova-tests : Set this flag if you want to create only nova resource tests.

--resource-name[=RESOURCE-NAME] : Override the default (App\\Nova\\ModelResource) Nova resource name. Used only with --only-nova-tests.

please, use flag variable with double screening and double quotes without Nova directory, for example --resource-name="Resources\\Banner\\BannerResource"

#### Mode combination options

--only-entity : Generate stack of classes to work with entity inside the app (Migration/Model/Service/Repository)
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"psr-4": {
"RonasIT\\Support\\Tests\\": "tests/",
"RonasIT\\Support\\Tests\\Support\\": "tests/Support/",
"App\\Nova\\": "tests/Support/Nova/"
"App\\Nova\\": "tests/Support/Nova/",
"Laravel\\Nova\\": "tests/Support/NovaResource"
},
"files": [
"tests/TestCase.php"
Expand Down
4 changes: 3 additions & 1 deletion src/Commands/MakeEntityCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ class MakeEntityCommand extends Command
{--only-seeder : Set this flag if you want to create only seeder.}
{--only-nova-resource : Set this flag if you want to create only nova resource.}
{--only-nova-tests : Set this flag if you want to create only nova resource tests.}

{--resource-name= : Override the default Nova resource name. Used only with --only-nova-tests.}

{--methods=CRUD : Set types of methods to create. Affect on routes, requests classes, controller\'s methods and tests methods.}

{--i|integer=* : Add integer field to entity.}
Expand Down Expand Up @@ -218,6 +219,7 @@ protected function runGeneration($generator)
->setFields($this->getFields())
->setRelations($this->getRelations())
->setCrudOptions($this->getCrudOptions())
->setMetaData(['resource_name' => $this->option('resource-name')])
->generate();
}

Expand Down
5 changes: 5 additions & 0 deletions src/Generators/EntityGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ public function setRelations(RelationsDTO $relations)
return $this;
}

public function setMetaData(array $data): self
{
return $this;
}

public function __construct()
{
$this->paths = config('entity-generator.paths');
Expand Down
124 changes: 99 additions & 25 deletions src/Generators/NovaTestGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,58 @@
use RonasIT\Support\Events\SuccessCreateMessage;
use RonasIT\Support\Exceptions\ClassAlreadyExistsException;
use RonasIT\Support\Exceptions\ClassNotExistsException;
use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;
use RonasIT\Support\Exceptions\EntityCreateException;
use Generator;

class NovaTestGenerator extends AbstractTestsGenerator
{
protected $novaModelName;
protected ?string $resourceName;

protected ?string $fullNovaResourcePath = null;

protected ?string $shortNovaResourceName;

protected string $novaPath;

public function __construct()
{
$this->novaPath = app_path('Nova');

parent::__construct();
}

public function generate(): void
{
if (class_exists(NovaServiceProvider::class)) {
if (!$this->doesNovaResourceExists()) {
if (!$this->classExists('models', $this->model)) {
$this->throwFailureException(
ClassNotExistsException::class,
"Cannot create Nova{$this->model}Resource Test cause {$this->model} does not exist.",
"Create a {$this->model} Model by himself or run command 'php artisan make:entity {$this->model} --only-model'."
);
}

$resource = $this->resourceName ?? $this->getNovaResource();

$this->shortNovaResourceName = Str::afterLast($resource, '\\');

$this->fullNovaResourcePath = "App\\Nova\\{$resource}";

if (!class_exists($this->fullNovaResourcePath)) {
$this->throwFailureException(
ClassNotExistsException::class,
"Cannot create Nova{$this->model}Test cause {$this->model} Nova resource does not exist.",
"Create {$this->model} Nova resource."
"Cannot create Nova{$this->shortNovaResourceName}Test cause {$this->resourceName} Nova resource does not exist.",
"Create {$this->resourceName} Nova resource."
);
}

if ($this->classExists('nova', "Nova{$this->model}Test")) {
if ($this->classExists('nova', "Nova{$this->shortNovaResourceName}Test")) {
$this->throwFailureException(
ClassAlreadyExistsException::class,
"Cannot create Nova{$this->model}Test cause it's already exist.",
"Remove Nova{$this->model}Test."
"Cannot create Nova{$this->shortNovaResourceName}Test cause it's already exist.",
"Remove Nova{$this->shortNovaResourceName}Test."
);
}

Expand All @@ -38,6 +69,13 @@ public function generate(): void
}
}

public function setMetaData(array $data): self
{
$this->resourceName = !empty($data['resource_name']) ? Str::studly($data['resource_name']) : null;

return $this;
}

public function generateTests(): void
{
if (!$this->isStubExists('nova_test')) {
Expand All @@ -58,9 +96,9 @@ public function generateTests(): void
'filters' => $filters,
]);

$this->saveClass('tests', "Nova{$this->model}Test", $fileContent);
$this->saveClass('tests', "Nova{$this->shortNovaResourceName}Test", $fileContent);

event(new SuccessCreateMessage("Created a new Nova test: Nova{$this->model}Test"));
event(new SuccessCreateMessage("Created a new Nova test: Nova{$this->shortNovaResourceName}Test"));
}

protected function getActions(): array
Expand All @@ -83,46 +121,82 @@ protected function getActions(): array

protected function loadNovaActions()
{
return app("\\App\\Nova\\{$this->novaModelName}")->actions(new NovaRequest());
return app("{$this->fullNovaResourcePath}")->actions(new NovaRequest());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return app("{$this->fullNovaResourcePath}")->actions(new NovaRequest());
return app($this->fullNovaResourcePath)->actions(new NovaRequest());

}

protected function loadNovaFields()
{
return app("\\App\\Nova\\{$this->novaModelName}")->fields(new NovaRequest());
return app("{$this->fullNovaResourcePath}")->fields(new NovaRequest());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return app("{$this->fullNovaResourcePath}")->fields(new NovaRequest());
return app($this->fullNovaResourcePath)->fields(new NovaRequest());

}

protected function loadNovaFilters()
{
return app("\\App\\Nova\\{$this->novaModelName}")->filters(new NovaRequest());
return app("{$this->fullNovaResourcePath}")->filters(new NovaRequest());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return app("{$this->fullNovaResourcePath}")->filters(new NovaRequest());
return app($this->fullNovaResourcePath)->filters(new NovaRequest());

}

public function getTestClassName(): string
{
return "Nova{$this->model}Test";
return "Nova{$this->shortNovaResourceName}Test";
}

protected function isFixtureNeeded($type): bool
{
return true;
}

protected function doesNovaResourceExists(): bool
protected function getNovaResource(): string
{
$commonResources = $this->getCommonNovaResources();

if (count($commonResources) > 1) {
$commonResources = implode(', ', $commonResources);

$this->throwFailureException(
EntityCreateException::class,
"Cannot create Nova{$this->model}Resource Test cause was found a lot of suitable resources: $commonResources",
"Please, use --resource-name option"
);
}

return array_pop($commonResources);
}

protected function getNovaFiles(): Generator
{
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->novaPath));

foreach ($iterator as $file) {
if ($file->isFile() && $file->getExtension() === 'php') {
yield $file;
}
}
}

protected function getCommonNovaResources(): array
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
protected function getCommonNovaResources(): array
protected function getCommonNovaResources(): array
{
$resources = [];
foreach ($this->getNovaFiles() as $file) {
$relativePath = Str::after($file->getPathname(), $this->novaPath . DIRECTORY_SEPARATOR);
$class = str_replace(['/', '.php'], ['\\', ''], $relativePath);
if ($this->isNovaResource($class) && $this->isResourceNameContainModel($class)) {
$resources[] = $class;
}
}
return $resources;
}

{
$possibleNovaModelNames = [
"{$this->model}NovaResource",
"{$this->model}Resource",
$this->model
];
$resources = [];

foreach ($this->getNovaFiles() as $file) {
$relativePath = Str::after($file->getPathname(), $this->novaPath . DIRECTORY_SEPARATOR);

foreach ($possibleNovaModelNames as $modelName) {
if ($this->classExists('nova', $modelName)) {
$this->novaModelName = $modelName;
$class = str_replace(['/', '.php'], ['\\', ''], $relativePath);

return true;
if ($this->isNovaResource($class) && $this->isResourceNameContainModel($class)) {
$resources[] = $class;
}
}

return false;
return $resources;
}

protected function isNovaResource(string $resource): bool
{
return is_subclass_of("App\\Nova\\{$resource}", "Laravel\\Nova\\Resource");
}

protected function isResourceNameContainModel(string $resource): bool
{
return Str::afterLast(str_replace('Resource', '', $resource), '\\') === $this->model;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

contain or hard equal? Are you sure? If resourse will have name WelcomeBonusDraftResource.php

}

protected function collectFilters(): array
Expand Down Expand Up @@ -160,7 +234,7 @@ protected function getFiltersFromFields(): array

protected function getFilters(): array
{
$filters= [];
$filters = [];
$novaResourceFilters = $this->loadNovaFilters();

foreach ($novaResourceFilters as $filter) {
Expand Down
1 change: 1 addition & 0 deletions stubs/nova_resource.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@foreach($types as $fieldType)
use Laravel\Nova\Fields\{{$fieldType}};
@endforeach
use Laravel\Nova\Resource;

class {{$model}}Resource extends Resource
{
Expand Down
58 changes: 53 additions & 5 deletions tests/CommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use RonasIT\Support\Tests\Support\Command\CommandMockTrait;
use RonasIT\Support\Tests\Support\Command\Models\Post;
use UnexpectedValueException;
use App\Nova\PostResource;

class CommandTest extends TestCase
{
Expand Down Expand Up @@ -51,6 +52,7 @@ public function testCallCommand()

$this->mockGenerator();
$this->mockGettingModelInstance(new Post());
$this->app->instance(PostResource::class, new PostResource());
$this->mockDBTransactionStartRollback(2);

$this
Expand Down Expand Up @@ -79,11 +81,11 @@ public function testCallCommand()
$this->assertGeneratedFileEquals('update_request.json', 'tests/fixtures/PostTest/update_post_request.json');
$this->assertGeneratedFileEquals('validation.php', 'lang/en/validation.php');
$this->assertGeneratedFileEquals('nova_resource.php', 'app/Nova/PostResource.php');
$this->assertGeneratedFileEquals('nova_test.php', 'tests/NovaPostTest.php');
$this->assertGeneratedFileEquals('nova_dump.php', 'tests/fixtures/NovaPostTest/nova_post_dump.sql');
$this->assertGeneratedFileEquals('create_request.json', 'tests/fixtures/NovaPostTest/create_post_request.json');
$this->assertGeneratedFileEquals('create_response.json', 'tests/fixtures/NovaPostTest/create_post_response.json');
$this->assertGeneratedFileEquals('update_request.json', 'tests/fixtures/NovaPostTest/update_post_request.json');
$this->assertGeneratedFileEquals('nova_test.php', 'tests/NovaPostResourceTest.php');
$this->assertGeneratedFileEquals('nova_dump.php', 'tests/fixtures/NovaPostResourceTest/nova_post_dump.sql');
$this->assertGeneratedFileEquals('create_request.json', 'tests/fixtures/NovaPostResourceTest/create_post_request.json');
$this->assertGeneratedFileEquals('create_response.json', 'tests/fixtures/NovaPostResourceTest/create_post_response.json');
$this->assertGeneratedFileEquals('update_request.json', 'tests/fixtures/NovaPostResourceTest/update_post_request.json');
}

public function testMakeOnly()
Expand Down Expand Up @@ -123,6 +125,52 @@ public function testMakeOnly()
$this->assertFileDoesNotExist('tests/fixtures/NovaPostTest/update_post_request.json');
}

public function testMakeOnlyNovaTest(): void
{
Carbon::setTestNow('2016-10-20 11:05:00');

$this->mockFilesystemWithPostModelAndResource();

config([
'entity-generator.paths.models' => 'RonasIT\Support\Tests\Support\Command\Models',
'entity-generator.paths.factories' => 'RonasIT\Support\Tests\Support\Command\Factories',
]);

$this->mockGeneratorOnlyNovaTests();

$this
->artisan('make:entity Post --only-nova-tests --resource-name=PostResource')
->assertSuccessful();

$this->assertFileDoesNotExist('app/Repositories/PostRepository.php');
$this->assertFileDoesNotExist('database/migrations/2016_10_20_110500_posts_create_table.php');
$this->assertFileDoesNotExist('database/factories/PostFactory.php');
$this->assertFileDoesNotExist('database/seeders/PostSeeder.php');
$this->assertFileDoesNotExist('app/Models/Post.php');
$this->assertFileDoesNotExist('app/Services/PostService.php');
$this->assertFileDoesNotExist('app/Http/Requests/Post/CreatePostRequest.php');
$this->assertFileDoesNotExist('app/Http/Requests/Post/GetPostRequest.php');
$this->assertFileDoesNotExist('app/Http/Requests/Post/SearchPostsRequest.php');
$this->assertFileDoesNotExist('app/Http/Requests/Post/UpdatePostRequest.php');
$this->assertFileDoesNotExist('app/Http/Requests/Post/DeletePostRequest.php');
$this->assertFileDoesNotExist('app/Http/Controllers/PostController.php');
$this->assertFileDoesNotExist('app/Http/Resources/Post/PostResource.php');
$this->assertFileDoesNotExist('app/Http/Resources/Post/PostsCollectionResource.php');
$this->assertFileDoesNotExist('routes/api.php');
$this->assertFileDoesNotExist('tests/PostTest.php');
$this->assertFileDoesNotExist('tests/fixtures/PostTest/dump.sql');
$this->assertFileDoesNotExist('tests/fixtures/PostTest/create_post_request.json');
$this->assertFileDoesNotExist('tests/fixtures/PostTest/create_post_response.json');
$this->assertFileDoesNotExist('tests/fixtures/PostTest/update_post_request.json');
$this->assertFileDoesNotExist('lang/en/validation.php');
$this->assertFileDoesNotExist('app/Nova/PostResource.php');
$this->assertGeneratedFileEquals('nova_test.php', 'tests/NovaPostResourceTest.php');
$this->assertGeneratedFileEquals('nova_dump.php', 'tests/fixtures/NovaPostResourceTest/nova_post_dump.sql');
$this->assertGeneratedFileEquals('create_request.json', 'tests/fixtures/NovaPostResourceTest/create_post_request.json');
$this->assertGeneratedFileEquals('create_response.json', 'tests/fixtures/NovaPostResourceTest/create_post_response.json');
$this->assertGeneratedFileEquals('update_request.json', 'tests/fixtures/NovaPostResourceTest/update_post_request.json');
}

public function testCallWithNotDefaultConfig()
{
$this->app->instance('path.base', $this->generatedFileBasePath);
Expand Down
Loading