diff --git a/src/Generators/EntityGenerator.php b/src/Generators/EntityGenerator.php index faf4c2f6..212784c8 100644 --- a/src/Generators/EntityGenerator.php +++ b/src/Generators/EntityGenerator.php @@ -26,7 +26,7 @@ abstract class EntityGenerator protected $paths = []; protected $model; protected $fields; - protected $relations; + protected $relations = []; protected $crudOptions; /** @@ -213,14 +213,14 @@ protected function getModelClass(string $model): string return "{$modelNamespace}\\{$model}"; } - protected function isStubExists(string $stubName): bool + protected function isStubExists(string $stubName, ?string $generationType = null): bool { $config = "entity-generator.stubs.{$stubName}"; $stubPath = config($config); if (!view()->exists($stubPath)) { - $generationType = Str::replace('_', ' ', $stubName); + $generationType ??= Str::replace('_', ' ', $stubName); $message = "Generation of {$generationType} has been skipped cause the view {$stubPath} from the config {$config} is not exists. Please check that config has the correct view name value."; diff --git a/src/Generators/ModelGenerator.php b/src/Generators/ModelGenerator.php index e113a386..15c11ce2 100644 --- a/src/Generators/ModelGenerator.php +++ b/src/Generators/ModelGenerator.php @@ -10,22 +10,22 @@ class ModelGenerator extends EntityGenerator { - CONST PLURAL_NUMBER_REQUIRED = [ + protected const array PLURAL_NUMBER_REQUIRED = [ 'belongsToMany', - 'hasMany' + 'hasMany', ]; public function generate(): void { if ($this->classExists('models', $this->model)) { $this->throwFailureException( - ClassAlreadyExistsException::class, - "Cannot create {$this->model} Model cause {$this->model} Model already exists.", - "Remove {$this->model} Model." + exceptionClass: ClassAlreadyExistsException::class, + failureMessage: "Cannot create {$this->model} Model cause {$this->model} Model already exists.", + recommendedMessage: "Remove {$this->model} Model.", ); } - if ($this->isStubExists('model') && ($this->isStubExists('relation') || empty($this->relations))) { + if ($this->isStubExists('model') && (!$this->hasRelations() || $this->isStubExists('relation', 'model'))) { $this->prepareRelatedModels(); $modelContent = $this->getNewModelContent(); @@ -35,6 +35,11 @@ public function generate(): void } } + protected function hasRelations(): bool + { + return !collect($this->relations)->every(fn ($relation) => empty($relation)); + } + protected function getNewModelContent(): string { return $this->getStub('model', [ @@ -42,7 +47,7 @@ protected function getNewModelContent(): string 'fields' => Arr::collapse($this->fields), 'relations' => $this->prepareRelations(), 'casts' => $this->getCasts($this->fields), - 'namespace' => $this->getOrCreateNamespace('models') + 'namespace' => $this->getOrCreateNamespace('models'), ]); } @@ -59,9 +64,9 @@ public function prepareRelatedModels(): void foreach ($relationsByType as $relation) { if (!$this->classExists('models', $relation)) { $this->throwFailureException( - ClassNotExistsException::class, - "Cannot create {$relation} Model cause {$relation} Model does not exists.", - "Create a {$relation} Model by himself or run command 'php artisan make:entity {$relation} --only-model'." + exceptionClass: ClassNotExistsException::class, + failureMessage: "Cannot create {$this->model} Model cause relation model {$relation} does not exist.", + recommendedMessage: "Create the {$relation} Model by himself or run command 'php artisan make:entity {$relation} --only-model'.", ); } @@ -70,7 +75,7 @@ public function prepareRelatedModels(): void $newRelation = $this->getStub('relation', [ 'name' => $this->getRelationName($this->model, $types[$type]), 'type' => $types[$type], - 'entity' => $this->model + 'entity' => $this->model, ]); $fixedContent = preg_replace('/\}$/', "\n {$newRelation}\n}", $content); @@ -80,9 +85,9 @@ public function prepareRelatedModels(): void } } - public function getModelContent($model): string + public function getModelContent(string $model): string { - $modelPath = base_path($this->paths['models'] . "/{$model}.php"); + $modelPath = base_path("{$this->paths['models']}/{$model}.php"); return file_get_contents($modelPath); } @@ -97,7 +102,7 @@ public function prepareRelations(): array $result[] = [ 'name' => $this->getRelationName($relation, $type), 'type' => $type, - 'entity' => $relation + 'entity' => $relation, ]; } } @@ -106,7 +111,7 @@ public function prepareRelations(): array return $result; } - protected function getCasts($fields): array + protected function getCasts(array $fields): array { $casts = [ 'boolean-required' => 'boolean', @@ -117,7 +122,7 @@ protected function getCasts($fields): array $result = []; foreach ($fields as $fieldType => $names) { - if (empty($casts[$fieldType])) { + if (!array_key_exists($fieldType, $casts)) { continue; } @@ -129,7 +134,7 @@ protected function getCasts($fields): array return $result; } - private function getRelationName($relation, $type): string + private function getRelationName(string $relation, string $type): string { $relationName = Str::snake($relation); diff --git a/stubs/model.blade.php b/stubs/model.blade.php index aa1694af..a7fe5a49 100644 --- a/stubs/model.blade.php +++ b/stubs/model.blade.php @@ -14,10 +14,6 @@ class {{$entity}} extends Model ]; protected $hidden = ['pivot']; -@foreach($relations as $relation) - - @include(config('entity-generator.stubs.relation'), $relation) -@endforeach @if(!empty($casts)) protected $casts = [ @@ -26,4 +22,9 @@ class {{$entity}} extends Model @endforeach ]; @endif +@foreach($relations as $relation) + + @include(config('entity-generator.stubs.relation'), $relation) + +@endforeach } \ No newline at end of file diff --git a/stubs/relation.blade.php b/stubs/relation.blade.php index 72fec665..7ad7c409 100644 --- a/stubs/relation.blade.php +++ b/stubs/relation.blade.php @@ -1,4 +1,4 @@ public function {{$name}}() { return $this->{{$type}}({{$entity}}::class); - } + } \ No newline at end of file diff --git a/tests/ControllerGeneratorTest.php b/tests/ControllerGeneratorTest.php index ac9f2484..96ce0f54 100644 --- a/tests/ControllerGeneratorTest.php +++ b/tests/ControllerGeneratorTest.php @@ -3,7 +3,6 @@ namespace RonasIT\Support\Tests; use Illuminate\Contracts\Filesystem\FileNotFoundException; -use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\View; use RonasIT\Support\Events\SuccessCreateMessage; use RonasIT\Support\Events\WarningEvent; @@ -16,13 +15,6 @@ class ControllerGeneratorTest extends TestCase { use ControllerGeneratorMockTrait; - public function setUp(): void - { - parent::setUp(); - - Event::fake(); - } - public function testControllerAlreadyExists() { $this->mockClass(ControllerGenerator::class, [ diff --git a/tests/FactoryGeneratorTest.php b/tests/FactoryGeneratorTest.php index 0d103dd9..b46b5eb5 100644 --- a/tests/FactoryGeneratorTest.php +++ b/tests/FactoryGeneratorTest.php @@ -14,13 +14,6 @@ class FactoryGeneratorTest extends TestCase { use FactoryMockTrait; - public function setUp(): void - { - parent::setUp(); - - Event::fake(); - } - public function testModelNotExists() { $this->assertExceptionThrew( @@ -57,7 +50,6 @@ className: ClassAlreadyExistsException::class, public function testProcessUnknownFieldType() { - $this->mockConfigurations(); $this->mockFilesystem(); $this->assertExceptionThrew( @@ -82,7 +74,6 @@ className: ViewException::class, public function testCreateSuccess() { - $this->mockConfigurations(); $this->mockFilesystem(); app(FactoryGenerator::class) diff --git a/tests/MigrationGeneratorTest.php b/tests/MigrationGeneratorTest.php index ac272a48..867a57f9 100644 --- a/tests/MigrationGeneratorTest.php +++ b/tests/MigrationGeneratorTest.php @@ -5,16 +5,11 @@ use Illuminate\Support\Carbon; use RonasIT\Support\Exceptions\UnknownFieldTypeException; use RonasIT\Support\Generators\MigrationGenerator; -use RonasIT\Support\Tests\Support\Migration\MigrationMockTrait; class MigrationGeneratorTest extends TestCase { - use MigrationMockTrait; - public function testSetUnknownFieldType() { - $this->setupConfigurations(); - $this->assertExceptionThrew( className: UnknownFieldTypeException::class, message: 'Unknown field type unknown-type in MigrationGenerator.', @@ -39,9 +34,6 @@ public function testCreateMigration() { Carbon::setTestNow('2022-02-02'); - $this->mockFilesystem(); - $this->setupConfigurations(); - app(MigrationGenerator::class) ->setModel('Post') ->setRelations([ @@ -67,9 +59,6 @@ public function testCreateMigrationMYSQL() Carbon::setTestNow('2022-02-02'); - $this->mockFilesystem(); - $this->setupConfigurations(); - app(MigrationGenerator::class) ->setModel('Post') ->setRelations([ diff --git a/tests/ModelGeneratorTest.php b/tests/ModelGeneratorTest.php new file mode 100644 index 00000000..73e96af1 --- /dev/null +++ b/tests/ModelGeneratorTest.php @@ -0,0 +1,143 @@ +mockClass(ModelGenerator::class, [ + $this->classExistsMethodCall(['models', 'Post']), + ]); + + $this->assertExceptionThrew( + className: ClassAlreadyExistsException::class, + message: 'Cannot create Post Model cause Post Model already exists. Remove Post Model.', + ); + + app(ModelGenerator::class) + ->setModel('Post') + ->generate(); + } + + public function testRelationModelMissing() + { + $this->assertExceptionThrew( + className: ClassNotExistsException::class, + message: "Cannot create Post Model cause relation model Comment does not exist. " + . "Create the Comment Model by himself or run command 'php artisan make:entity Comment --only-model'.", + ); + + app(ModelGenerator::class) + ->setModel('Post') + ->setRelations([ + 'hasOne' => ['Comment'], + 'hasMany' => [], + 'belongsTo' => [], + 'belongsToMany' => [], + ]) + ->generate(); + } + + public function testCreateModel() + { + $this->mockFilesystem(); + + app(ModelGenerator::class) + ->setModel('Post') + ->setFields([ + 'integer-required' => ['media_id'], + 'boolean-required' => ['is_published'], + ]) + ->setRelations([ + 'hasOne' => ['Comment'], + 'hasMany' => ['User'], + 'belongsTo' => [], + 'belongsToMany' => [], + ]) + ->generate(); + + $this->assertGeneratedFileEquals('new_model.php', 'app/Models/Post.php'); + $this->assertGeneratedFileEquals('comment_relation_model.php', 'app/Models/Comment.php'); + $this->assertGeneratedFileEquals('comment_relation_model.php', 'app/Models/User.php'); + + $this->assertEventPushed( + className: SuccessCreateMessage::class, + message: 'Created a new Model: Post', + ); + } + + public function testCreateModelStubNotExist() + { + $this->mockFilesystem(); + + config(['entity-generator.stubs.model' => 'incorrect_stub']); + + app(ModelGenerator::class) + ->setModel('Post') + ->setFields([]) + ->generate(); + + $this->assertFileDoesNotExist('app/Models/Post.php'); + $this->assertFileDoesNotExist('app/Models/Comment.php'); + $this->assertFileDoesNotExist('app/Models/User.php'); + + $this->assertEventPushed( + className: WarningEvent::class, + message: 'Generation of model has been skipped cause the view incorrect_stub from the config entity-generator.stubs.model is not exists. Please check that config has the correct view name value.', + ); + } + + public function testCreateModelWithoutRelationsRelationStubNotExist() + { + $this->mockFilesystem(); + + config(['entity-generator.stubs.relation' => 'incorrect_stub']); + + app(ModelGenerator::class) + ->setModel('Post') + ->setFields([]) + ->generate(); + + $this->assertGeneratedFileEquals('new_model_without_fields_and_relations.php', 'app/Models/Post.php'); + + $this->assertEventPushed( + className: SuccessCreateMessage::class, + message: 'Created a new Model: Post', + ); + } + + public function testCreateModelWithRelationsRelationStubNotExist() + { + $this->mockFilesystem(); + + config(['entity-generator.stubs.relation' => 'incorrect_stub']); + + app(ModelGenerator::class) + ->setModel('Post') + ->setFields([]) + ->setRelations([ + 'hasOne' => ['Comment'], + 'hasMany' => ['User'], + 'belongsTo' => [], + 'belongsToMany' => [], + ]) + ->generate(); + + $this->assertFileDoesNotExist('new_model.php', 'app/Models/Post.php'); + + $this->assertEventPushed( + className: WarningEvent::class, + message: 'Generation of model has been skipped cause the view incorrect_stub from the config entity-generator.stubs.relation is not exists. Please check that config has the correct view name value.', + ); + } +} diff --git a/tests/NovaResourceGeneratorTest.php b/tests/NovaResourceGeneratorTest.php index 4e7710e1..5a5b897f 100644 --- a/tests/NovaResourceGeneratorTest.php +++ b/tests/NovaResourceGeneratorTest.php @@ -2,7 +2,6 @@ namespace RonasIT\Support\Tests; -use Illuminate\Support\Facades\Event; use RonasIT\Support\Events\SuccessCreateMessage; use RonasIT\Support\Events\WarningEvent; use RonasIT\Support\Exceptions\ClassAlreadyExistsException; @@ -14,13 +13,6 @@ class NovaResourceGeneratorTest extends TestCase { use NovaResourceGeneratorMockTrait; - public function setUp(): void - { - parent::setUp(); - - Event::fake(); - } - public function testCreateWithMissingNovaPackage() { $this->mockNovaServiceProviderExists(false); diff --git a/tests/NovaTestGeneratorTest.php b/tests/NovaTestGeneratorTest.php index be1a052b..8b3fe11e 100644 --- a/tests/NovaTestGeneratorTest.php +++ b/tests/NovaTestGeneratorTest.php @@ -3,7 +3,6 @@ namespace RonasIT\Support\Tests; use RonasIT\Support\Tests\Support\Models\WelcomeBonus; -use Illuminate\Support\Facades\Event; use RonasIT\Support\Events\SuccessCreateMessage; use RonasIT\Support\Events\WarningEvent; use RonasIT\Support\Exceptions\ClassAlreadyExistsException; @@ -58,8 +57,6 @@ className: ClassAlreadyExistsException::class, public function testNovaTestStubNotExist() { - Event::fake(); - $this->mockNativeGeneratorFunctions( $this->nativeClassExistsMethodCall([NovaServiceProvider::class, true]), $this->nativeClassExistsMethodCall([WelcomeBonus::class, true]), @@ -96,8 +93,6 @@ className: WarningEvent::class, public function testDumpStubNotExist() { - Event::fake(); - $this->mockNovaServiceProviderExists(); $this->mockFilesystem(); @@ -156,8 +151,6 @@ public function testSuccess() public function testGenerateNovaPackageNotInstall() { - Event::fake(); - $this->mockNovaServiceProviderExists(false); app(NovaTestGenerator::class) diff --git a/tests/SeederGeneratorTest.php b/tests/SeederGeneratorTest.php index 167b4821..96b56bc5 100644 --- a/tests/SeederGeneratorTest.php +++ b/tests/SeederGeneratorTest.php @@ -2,26 +2,13 @@ namespace RonasIT\Support\Tests; -use Illuminate\Support\Facades\Event; use RonasIT\Support\Events\WarningEvent; use RonasIT\Support\Generators\SeederGenerator; -use RonasIT\Support\Tests\Support\SeederGeneratorMockTrait; class SeederGeneratorTest extends TestCase { - use SeederGeneratorMockTrait; - - public function setUp(): void - { - parent::setUp(); - - Event::fake(); - } - public function testCreateSeeder() { - $this->mockFilesystem(); - app(SeederGenerator::class) ->setRelations([ 'hasOne' => [], @@ -38,8 +25,6 @@ public function testCreateSeeder() public function testCreateSeederEmptyDatabaseSeederStubNotExist() { - $this->mockFilesystem(); - config(['entity-generator.stubs.database_empty_seeder' => 'entity-generator::database_seed_empty']); app(SeederGenerator::class) @@ -63,8 +48,6 @@ className: WarningEvent::class, public function testCreateSeederEntityDatabaseSeederStubNotExist() { - $this->mockFilesystem(); - config(['entity-generator.stubs.seeder' => 'incorrect_stub']); app(SeederGenerator::class) diff --git a/tests/Support/ControllerGeneratorTest/ControllerGeneratorMockTrait.php b/tests/Support/ControllerGeneratorTest/ControllerGeneratorMockTrait.php index 67f9374b..fb39a019 100644 --- a/tests/Support/ControllerGeneratorTest/ControllerGeneratorMockTrait.php +++ b/tests/Support/ControllerGeneratorTest/ControllerGeneratorMockTrait.php @@ -4,12 +4,10 @@ use RonasIT\Support\Tests\Support\FileSystemMock; use RonasIT\Support\Tests\Support\GeneratorMockTrait; -use RonasIT\Support\Traits\MockTrait; trait ControllerGeneratorMockTrait { use GeneratorMockTrait; - use MockTrait; public function mockFilesystemWithoutRoutesFile(): void { diff --git a/tests/Support/Factory/FactoryMockTrait.php b/tests/Support/Factory/FactoryMockTrait.php index 60a4b920..0e9bb17f 100644 --- a/tests/Support/Factory/FactoryMockTrait.php +++ b/tests/Support/Factory/FactoryMockTrait.php @@ -2,44 +2,28 @@ namespace RonasIT\Support\Tests\Support\Factory; -use org\bovigo\vfs\vfsStream; use RonasIT\Support\Generators\FactoryGenerator; +use RonasIT\Support\Tests\Support\FileSystemMock; use RonasIT\Support\Tests\Support\GeneratorMockTrait; -use RonasIT\Support\Traits\MockTrait; trait FactoryMockTrait { - use GeneratorMockTrait, MockTrait; + use GeneratorMockTrait; public function mockFactoryGenerator(array ...$functionCalls): void { $this->mockClass(FactoryGenerator::class, $functionCalls); } - public function mockConfigurations(): void - { - config([ - 'entity-generator.paths' => [ - 'models' => 'app/Models', - 'factories' => 'database/factories', - ], - ]); - } - public function mockFilesystem(): void { - $structure = [ - 'app' => [ - 'Models' => [ - 'Post.php' => $this->mockPhpFileContent(), - 'User.php' => $this->mockPhpFileContent(), - ], - ], - 'database' => [ - 'factories' => [], - ], + $fileSystemMock = new FileSystemMock(); + + $fileSystemMock->models = [ + 'Post.php' => $this->mockPhpFileContent(), + 'User.php' => $this->mockPhpFileContent(), ]; - vfsStream::create($structure); + $fileSystemMock->setStructure(); } } diff --git a/tests/Support/GeneratorMockTrait.php b/tests/Support/GeneratorMockTrait.php index 5933ed8d..09ef73bc 100644 --- a/tests/Support/GeneratorMockTrait.php +++ b/tests/Support/GeneratorMockTrait.php @@ -3,9 +3,12 @@ namespace RonasIT\Support\Tests\Support; use Laravel\Nova\NovaServiceProvider; +use RonasIT\Support\Traits\MockTrait; trait GeneratorMockTrait { + use MockTrait; + public function mockNativeGeneratorFunctions(...$functionCalls): void { $this->mockNativeFunction('\RonasIT\Support\Generators', $functionCalls); diff --git a/tests/Support/Migration/MigrationMockTrait.php b/tests/Support/Migration/MigrationMockTrait.php deleted file mode 100644 index 05b88f7c..00000000 --- a/tests/Support/Migration/MigrationMockTrait.php +++ /dev/null @@ -1,32 +0,0 @@ - 'entity-generator::migration', - 'entity-generator.paths' => [ - 'migrations' => 'database/migrations', - ] - ]); - } - - public function mockFilesystem(): void - { - $structure = [ - 'database' => [ - 'migrations' => [], - ], - ]; - - vfsStream::create($structure); - } -} diff --git a/tests/Support/Model/ModelMockTrait.php b/tests/Support/Model/ModelMockTrait.php new file mode 100644 index 00000000..dad2d4ea --- /dev/null +++ b/tests/Support/Model/ModelMockTrait.php @@ -0,0 +1,23 @@ +models = [ + 'Comment.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'), + 'User.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'), + ]; + + $fileSystemMock->setStructure(); + } +} diff --git a/tests/Support/Models/WelcomeBonus.php b/tests/Support/Models/WelcomeBonus.php index dcc84688..027f2c36 100644 --- a/tests/Support/Models/WelcomeBonus.php +++ b/tests/Support/Models/WelcomeBonus.php @@ -18,4 +18,8 @@ public function getConnectionName(): string 'title', 'name', ]; + + public function some_relation() + { + } } \ No newline at end of file diff --git a/tests/Support/NovaResourceGeneratorTest/NovaResourceGeneratorMockTrait.php b/tests/Support/NovaResourceGeneratorTest/NovaResourceGeneratorMockTrait.php index c0a7f5d1..77410f91 100644 --- a/tests/Support/NovaResourceGeneratorTest/NovaResourceGeneratorMockTrait.php +++ b/tests/Support/NovaResourceGeneratorTest/NovaResourceGeneratorMockTrait.php @@ -7,12 +7,10 @@ use Mockery; use RonasIT\Support\Tests\Support\FileSystemMock; use RonasIT\Support\Tests\Support\GeneratorMockTrait; -use RonasIT\Support\Traits\MockTrait; trait NovaResourceGeneratorMockTrait { use GeneratorMockTrait; - use MockTrait; public function mockFilesystem(): void { diff --git a/tests/Support/NovaTestGeneratorTest/NovaTestGeneratorMockTrait.php b/tests/Support/NovaTestGeneratorTest/NovaTestGeneratorMockTrait.php index d23aa284..4b3b074e 100644 --- a/tests/Support/NovaTestGeneratorTest/NovaTestGeneratorMockTrait.php +++ b/tests/Support/NovaTestGeneratorTest/NovaTestGeneratorMockTrait.php @@ -5,12 +5,10 @@ use Mockery; use RonasIT\Support\Tests\Support\FileSystemMock; use RonasIT\Support\Tests\Support\GeneratorMockTrait; -use RonasIT\Support\Traits\MockTrait; trait NovaTestGeneratorMockTrait { use GeneratorMockTrait; - use MockTrait; public function mockNovaRequestClassCall(): void { diff --git a/tests/Support/SeederGeneratorMockTrait.php b/tests/Support/SeederGeneratorMockTrait.php deleted file mode 100644 index 455597a1..00000000 --- a/tests/Support/SeederGeneratorMockTrait.php +++ /dev/null @@ -1,19 +0,0 @@ - [] - ]; - - vfsStream::create($structure); - } -} \ No newline at end of file diff --git a/tests/TestCase.php b/tests/TestCase.php index a5c0f83c..00e70300 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -28,6 +28,8 @@ public function setUp(): void vfsStream::setup(); + Event::fake(); + $this->generatedFileBasePath = vfsStream::url('root'); $this->app->setBasePath($this->generatedFileBasePath); diff --git a/tests/fixtures/ModelGeneratorTest/comment_relation_model.php b/tests/fixtures/ModelGeneratorTest/comment_relation_model.php new file mode 100644 index 00000000..1e42f1d6 --- /dev/null +++ b/tests/fixtures/ModelGeneratorTest/comment_relation_model.php @@ -0,0 +1,30 @@ +belongsTo(Post::class); + } +} \ No newline at end of file diff --git a/tests/fixtures/ModelGeneratorTest/new_model.php b/tests/fixtures/ModelGeneratorTest/new_model.php new file mode 100644 index 00000000..4aa5bb05 --- /dev/null +++ b/tests/fixtures/ModelGeneratorTest/new_model.php @@ -0,0 +1,32 @@ + 'boolean', + ]; + + public function comment() + { + return $this->hasOne(Comment::class); + } + + public function users() + { + return $this->hasMany(User::class); + } +} \ No newline at end of file diff --git a/tests/fixtures/ModelGeneratorTest/new_model_without_fields_and_relations.php b/tests/fixtures/ModelGeneratorTest/new_model_without_fields_and_relations.php new file mode 100644 index 00000000..4a643d9b --- /dev/null +++ b/tests/fixtures/ModelGeneratorTest/new_model_without_fields_and_relations.php @@ -0,0 +1,16 @@ +