Mercurial > packages > magicforger
changeset 37:116b36f5e73b ls_dev_2025_09
Adding support for tests. It's pretty basic but we can improve later.
| author | Luka Sitas <sitas.luka.97@gmail.com> |
|---|---|
| date | Thu, 25 Sep 2025 19:58:01 -0400 |
| parents | 76584181267a |
| children | c062f013fd19 |
| files | src/Generator/Generator.php src/Generator/Test/TestGenerator.php src/Generator/Test/stubs/test.stub src/MagicForgerServiceProvider.php src/Replacer/Replacer.php |
| diffstat | 5 files changed, 237 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/Generator/Generator.php Sat Sep 20 17:14:29 2025 -0400 +++ b/src/Generator/Generator.php Thu Sep 25 19:58:01 2025 -0400 @@ -82,6 +82,10 @@ if ($this->option('route')) { $this->createRoute(); } + + if ($this->option('test')) { + $this->createTest(); + } } /** @@ -96,7 +100,8 @@ ['request', 'r', InputOption::VALUE_NONE, 'Generate base request classes for the table.'], ['view', '', InputOption::VALUE_NONE, 'Generate base views for the table.'], ['route', 'w', InputOption::VALUE_NONE, 'Generate base routes classes for the table.'], - ['factory', 'f', InputOption::VALUE_NONE, 'Generate base factory classes for the table.'], + ['factory', 'F', InputOption::VALUE_NONE, 'Generate base factory classes for the table.'], + ['test', 't', InputOption::VALUE_NONE, 'Generate base test classes for the table.'], ]); } @@ -136,4 +141,9 @@ { $this->call('mf:factory', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh')]); } + + protected function createTest() + { + $this->call('mf:test', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh')]); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Generator/Test/TestGenerator.php Thu Sep 25 19:58:01 2025 -0400 @@ -0,0 +1,79 @@ +<?php + +namespace Wizard\MagicForger\Generator\Test; + +use Symfony\Component\Console\Attribute\AsCommand; +use Wizard\MagicForger\Generator\BaseGenerator; +use Wizard\MagicForger\Replacer; +use Illuminate\Support\Str; + +#[AsCommand(name: 'mf:test')] +class TestGenerator extends BaseGenerator +{ + /** + * The name and signature of the console command. + * + * @var string + */ + protected $name = 'mf:test'; + + /** + * The console command description. + * + * @var string + */ + protected $description = 'Generates the Test File for a table.'; + + /** + * The type of class being generated. + * + * @var string + */ + protected $type = 'Test'; + + /** + * Execute the console command. + */ + public function handle() + { + parent::handle(); + } + + /** + * Get the stub file for the generator. + * + * @return string + */ + protected function getStub() + { + return $this->resolveStubPath('/stubs/test.stub'); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * @return string + */ + protected function resolveStubPath($stub) + { + return is_file($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + protected function getClassName($name) + { + return $this->test_name($name); + } + + /** + * Get the stub file for the generator. + * + * @return string + */ + protected function getPath($name = null) + { + return str_replace(['App\\', '\\'], ['app/', '/'], $this->getTestNamespace() . '/' . $this->test_name($this->getTableInput()) . '.php'); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Generator/Test/stubs/test.stub Thu Sep 25 19:58:01 2025 -0400 @@ -0,0 +1,127 @@ +<?php + +namespace Tests\CRUD\{{ model }}; + +use {{ namespacedModel }}; +use App\Models\User; +use Wizard\Framework\Tests\TestCase; + +class {{ class }} extends TestCase +{ + /* use RefreshDatabase; */ + + public function test_{{ modelVariable }}_crud_index_access(): void + { + $response = $this + ->get(route('{{ tableName }}.index')); + + $response->assertStatus(200); + } + + public function test_{{ modelVariable }}_crud_get_data_access(): void + { + $response = $this + ->post(route('{{ tableName }}.get_data')); + + $response->assertStatus(200); + } + + public function test_{{ modelVariable }}_crud_create_access(): void + { + $response = $this + ->get(route('{{ tableName }}.create')); + + $response->assertStatus(200); + } + + public function test_{{ modelVariable }}_crud_edit_access(): void + { + $item = {{ model }}::factory()->create(); + + $response = $this + ->get(route('{{ tableName }}.edit', $item)); + + $response->assertStatus(200); + } + + public function test_{{ modelVariable }}_crud_create_usage(): void + { + $item = {{ model }}::factory()->make(); + + $response = $this + ->from(route('{{ tableName }}.create')) + ->post(route('{{ tableName }}.store'), + $item->toArray() + ); + + $response + ->assertSessionHasNoErrors() + ->assertRedirect(route('{{ tableName }}.index')); + + $this->assertDatabaseHas('{{ tableName }}', $item->toArray()); + } + + public function test_{{ modelVariable }}_crud_create_invalid_data(): void + { + $response = $this + ->from(route('{{ tableName }}.create')) + ->post(route('{{ tableName }}.store'), []); + + $response + ->assertSessionHasErrors() + ->assertRedirect(route('{{ tableName }}.create')); + + // Make sure no entry was added + $this->assertDatabaseCount('{{ tableName }}', 0); + } + + public function test_{{ modelVariable }}_crud_update_usage(): void + { + $item = {{ model }}::factory()->create(); + + $updateData = {{ model }}::factory()->make()->toArray(); + + $response = $this + ->from(route('{{ tableName }}.edit', $item)) + ->put(route('{{ tableName }}.update', $item), $updateData); + + $response + ->assertSessionHasNoErrors() + ->assertRedirect(route('{{ tableName }}.index')); + + $this->assertDatabaseHas('{{ tableName }}', $updateData); + } + + public function test_{{ modelVariable }}_crud_edit_invalid_data(): void + { + $item = {{ model }}::factory()->create(); + + $response = $this + ->from(route('{{ tableName }}.edit', $item)) + ->put(route('{{ tableName }}.update', $item), []); + + $response + ->assertSessionHasErrors() + ->assertRedirect(route('{{ tableName }}.edit', $item)); + + // Make sure no entry was added + $this->assertDatabaseHas('games', array_intersect(array_flip($item->getFillable()), $item->toArray())); + } + + public function test_{{ modelVariable }}_crud_delete_usage(): void + { + $item = {{ model }}::factory()->create(); + + $response = $this + ->delete(route('{{ tableName }}.destroy', $item)); + + $response + ->assertSessionHasNoErrors() + ->assertRedirect(route('{{ tableName }}.index')); + + $this->assertSoftDeleted('{{ tableName }}', [ + 'id' => $item->id, + ]); + } + +}
--- a/src/MagicForgerServiceProvider.php Sat Sep 20 17:14:29 2025 -0400 +++ b/src/MagicForgerServiceProvider.php Thu Sep 25 19:58:01 2025 -0400 @@ -12,6 +12,7 @@ use Wizard\MagicForger\Generator\Requests\StoreRequestGenerator; use Wizard\MagicForger\Generator\Requests\UpdateRequestGenerator; use Wizard\MagicForger\Generator\Route\RouteGenerator; +use Wizard\MagicForger\Generator\Test\TestGenerator; use Wizard\MagicForger\Generator\View\ViewGenerator; use Wizard\MagicForger\Generator\View\IndexViewGenerator; use Wizard\MagicForger\Generator\View\CreateEditViewGenerator; @@ -39,6 +40,7 @@ CreateEditViewGenerator::class, ShowViewGenerator::class, FactoryGenerator::class, + TestGenerator::class, ]); }
--- a/src/Replacer/Replacer.php Sat Sep 20 17:14:29 2025 -0400 +++ b/src/Replacer/Replacer.php Thu Sep 25 19:58:01 2025 -0400 @@ -165,6 +165,14 @@ return Str::singular(Str::studly($name)) . 'Factory'; } + /** + * Generate test name in Studly case. + */ + public function test_name(string $name): string + { + return Str::singular(Str::studly($name)) . 'Test'; + } + // Namespace Methods // These methods handle the formation of various namespaces used within the replacements. @@ -285,6 +293,16 @@ } /** + * Get the test namespace. + */ + public function getTestNamespace(string $name = ''): string + { + return base_path() + . DIRECTORY_SEPARATOR . 'tests' + . DIRECTORY_SEPARATOR . 'CRUD' ; + } + + /** * Get the request uses string for replacement. */ public function getRequestUses(string $name): string
