From 136e79f42061f6e6d3a53f22b60e32a5a355ec97 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Sat, 16 Sep 2023 02:34:36 +0100 Subject: [PATCH] Complete tests for generate migrations command --- .../Commands/GenerateMigrationTest.php | 401 ++++++++++++++++-- 1 file changed, 366 insertions(+), 35 deletions(-) diff --git a/tests/Console/Commands/GenerateMigrationTest.php b/tests/Console/Commands/GenerateMigrationTest.php index 9028443b..e1350a51 100644 --- a/tests/Console/Commands/GenerateMigrationTest.php +++ b/tests/Console/Commands/GenerateMigrationTest.php @@ -9,6 +9,7 @@ use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\File; +use Illuminate\Support\Facades\Schema; use Spatie\TestTime\TestTime; use SplFileInfo; @@ -22,9 +23,8 @@ public function setUp(): void Config::set('runway', [ 'resources' => [ - Food::class => [ - '', - ], + Food::class => [''], + Drink::class => [''], ], ]); @@ -33,10 +33,78 @@ public function setUp(): void }); } + public function tearDown(): void + { + parent::tearDown(); + + collect(File::allFiles(database_path('migrations')))->each(function (SplFileInfo $file) { + File::delete($file->getRealPath()); + }); + } + /** @test */ public function can_generate_migrations_for_multiple_resources() { - $this->markTestIncomplete(); + TestTime::freeze(); + + Config::set('runway', [ + 'resources' => [ + Food::class => [ + 'name' => 'Food', + 'blueprint' => [ + 'tabs' => [ + 'main' => [ + 'fields' => [ + ['handle' => 'name', 'field' => ['type' => 'text', 'validate' => 'required']], + ['handle' => 'metadata->calories', 'field' => ['type' => 'integer', 'validate' => 'required']], + ], + ], + ], + ], + ], + Drink::class => [ + 'name' => 'Drink', + 'blueprint' => [ + 'tabs' => [ + 'main' => [ + 'fields' => [ + ['handle' => 'name', 'field' => ['type' => 'text', 'validate' => 'required']], + ['handle' => 'metadata->calories', 'field' => ['type' => 'integer', 'validate' => 'required']], + ], + ], + ], + ], + ], + ], + ]); + + Runway::discoverResources(); + + $this + ->artisan('runway:generate-migrations') + ->expectsQuestion('Should we run your migrations?', 'no') + ->execute(); + + $this->assertFileExists( + $expectedFoodsMigrationPath = database_path().'/migrations/'.date('Y_m_d_His').'_create_foods_table.php' + ); + + $this->assertStringContainsString('return new class extends Migration', File::get($expectedFoodsMigrationPath)); + $this->assertStringContainsString("Schema::create('foods', function (Blueprint", File::get($expectedFoodsMigrationPath)); + $this->assertStringContainsString('$table->text(\'name\')', File::get($expectedFoodsMigrationPath)); + $this->assertStringContainsString('$table->json(\'metadata\')', File::get($expectedFoodsMigrationPath)); + + $this->assertFileExists( + $expectedDrinksMigrationPath = database_path().'/migrations/'.date('Y_m_d_His').'_create_drinks_table.php' + ); + + $this->assertStringContainsString('return new class extends Migration', File::get($expectedDrinksMigrationPath)); + $this->assertStringContainsString("Schema::create('drinks', function (Blueprint", File::get($expectedDrinksMigrationPath));; + $this->assertStringContainsString('$table->text(\'name\')', File::get($expectedDrinksMigrationPath)); + $this->assertStringContainsString('$table->json(\'metadata\')', File::get($expectedDrinksMigrationPath)); + + $this->assertFalse(Schema::hasTable('foods')); + $this->assertFalse(Schema::hasTable('drinks')); } /** @test */ @@ -52,20 +120,8 @@ public function can_generate_migration_for_single_resource() 'tabs' => [ 'main' => [ 'fields' => [ - [ - 'handle' => 'name', - 'field' => [ - 'type' => 'text', - 'validate' => 'required', - ], - ], - [ - 'handle' => 'metadata->calories', - 'field' => [ - 'type' => 'integer', - 'validate' => 'required', - ], - ], + ['handle' => 'name', 'field' => ['type' => 'text', 'validate' => 'required']], + ['handle' => 'metadata->calories', 'field' => ['type' => 'integer', 'validate' => 'required']], ], ], ], @@ -76,7 +132,6 @@ public function can_generate_migration_for_single_resource() Runway::discoverResources(); - // Run the command $this ->artisan('runway:generate-migrations', [ 'resource' => 'food', @@ -84,59 +139,326 @@ public function can_generate_migration_for_single_resource() ->expectsQuestion('Should we run your migrations?', 'no') ->execute(); - // Assert migration now exists $this->assertFileExists( $expectedMigrationPath = database_path().'/migrations/'.date('Y_m_d_His').'_create_foods_table.php' ); - // Assert migration is using the anonymous class syntax $this->assertStringContainsString('return new class extends Migration', File::get($expectedMigrationPath)); - - // Assert migration contains the right fields $this->assertStringContainsString('$table->text(\'name\')', File::get($expectedMigrationPath)); $this->assertStringContainsString('$table->json(\'metadata\')', File::get($expectedMigrationPath)); - // Cleanup after ourselves - collect(File::allFiles(database_path('migrations'))) - ->each(function (SplFileInfo $file) { - File::delete($file->getRealPath()); - }); + $this->assertFalse(Schema::hasTable('foods')); } /** @test */ - public function can_generate_migration_where_table_already_exists() + public function cant_generate_migration_where_table_already_exists() { - $this->markTestIncomplete(); + TestTime::freeze(); + + Config::set('runway', [ + 'resources' => [ + Food::class => [ + 'name' => 'Food', + 'blueprint' => [ + 'tabs' => [ + 'main' => [ + 'fields' => [ + ['handle' => 'name', 'field' => ['type' => 'text', 'validate' => 'required']], + ['handle' => 'metadata->calories', 'field' => ['type' => 'integer', 'validate' => 'required']], + ], + ], + ], + ], + ], + ], + ]); + + Runway::discoverResources(); + + Schema::shouldReceive('hasTable') + ->with('foods') + ->andReturn(true); + + Schema::shouldReceive('dropIfExists'); + + $this + ->artisan('runway:generate-migrations', [ + 'resource' => 'food', + ]) + ->expectsQuestion('Should we run your migrations?', 'no') + ->expectsOutput('Table [foods] already exists. Runway is not smart enough yet to update existing migrations. Sorry!') + ->execute(); + + $this->assertFileDoesNotExist(database_path().'/migrations/'.date('Y_m_d_His').'_create_foods_table.php'); } /** @test */ public function can_generate_migration_and_run_them_afterwards() { - $this->markTestIncomplete(); + TestTime::freeze(); + + Config::set('runway', [ + 'resources' => [ + Food::class => [ + 'name' => 'Food', + 'blueprint' => [ + 'tabs' => [ + 'main' => [ + 'fields' => [ + ['handle' => 'name', 'field' => ['type' => 'text', 'validate' => 'required']], + ['handle' => 'metadata->calories', 'field' => ['type' => 'integer', 'validate' => 'required']], + ], + ], + ], + ], + ], + ], + ]); + + Runway::discoverResources(); + + $this->assertFalse(Schema::hasTable('foods')); + + $this + ->artisan('runway:generate-migrations', [ + 'resource' => 'food', + ]) + ->expectsQuestion('Should we run your migrations?', 'yes') + ->execute(); + + $this->assertFileExists(database_path().'/migrations/'.date('Y_m_d_His').'_create_foods_table.php'); + + $this->assertTrue(Schema::hasTable('foods')); } /** @test */ public function can_generate_migration_and_ensure_normal_field_is_correct() { - $this->markTestIncomplete(); + TestTime::freeze(); + + Config::set('runway', [ + 'resources' => [ + Food::class => [ + 'name' => 'Food', + 'blueprint' => [ + 'tabs' => [ + 'main' => [ + 'fields' => [ + [ + 'handle' => 'ramond_the_array', + 'field' => [ + 'type' => 'array', + ], + ], + [ + 'handle' => 'the_big_red_button', + 'field' => [ + 'type' => 'button_group', + ], + ], + [ + 'handle' => 'floating_away', + 'field' => [ + 'type' => 'float', + ], + ], + [ + 'handle' => 'int_the_ant', + 'field' => [ + 'type' => 'integer', + ], + ], + [ + 'handle' => 'toggle_me_smth', + 'field' => [ + 'type' => 'toggle', + ], + ], + [ + 'handle' => 'author_id', + 'field' => [ + 'type' => 'belongs_to', + ], + ], + ], + ], + ], + ], + ], + ], + ]); + + Runway::discoverResources(); + + $this + ->artisan('runway:generate-migrations', [ + 'resource' => 'food', + ]) + ->expectsQuestion('Should we run your migrations?', 'no') + ->execute(); + + $this->assertFileExists( + $expectedMigrationPath = database_path().'/migrations/'.date('Y_m_d_His').'_create_foods_table.php' + ); + + $this->assertStringContainsString('return new class extends Migration', File::get($expectedMigrationPath)); + + $this->assertStringContainsString('$table->json(\'ramond_the_array\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->string(\'the_big_red_button\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->float(\'floating_away\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->integer(\'int_the_ant\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->boolean(\'toggle_me_smth\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->bigInteger(\'author_id\')', File::get($expectedMigrationPath)); + + $this->assertFalse(Schema::hasTable('foods')); } /** @test */ public function can_generate_migration_and_ensure_max_items_1_field_is_correct() { - $this->markTestIncomplete(); + TestTime::freeze(); + + Config::set('runway', [ + 'resources' => [ + Food::class => [ + 'name' => 'Food', + 'blueprint' => [ + 'tabs' => [ + 'main' => [ + 'fields' => [ + ['handle' => 'assets', 'field' => ['type' => 'assets']], + ['handle' => 'collections', 'field' => ['type' => 'collections']], + ['handle' => 'entries', 'field' => ['type' => 'entries']], + ['handle' => 'terms', 'field' => ['type' => 'terms']], + ['handle' => 'users', 'field' => ['type' => 'users']], + + ['handle' => 'asset', 'field' => ['type' => 'assets', 'max_items' => 1]], + ['handle' => 'collection', 'field' => ['type' => 'collections', 'max_items' => 1]], + ['handle' => 'entry', 'field' => ['type' => 'entries', 'max_items' => 1]], + ['handle' => 'term', 'field' => ['type' => 'terms', 'max_items' => 1]], + ['handle' => 'user', 'field' => ['type' => 'users', 'max_items' => 1]], + ], + ], + ], + ], + ], + ], + ]); + + Runway::discoverResources(); + + $this + ->artisan('runway:generate-migrations', [ + 'resource' => 'food', + ]) + ->expectsQuestion('Should we run your migrations?', 'no') + ->execute(); + + $this->assertFileExists( + $expectedMigrationPath = database_path().'/migrations/'.date('Y_m_d_His').'_create_foods_table.php' + ); + + $this->assertStringContainsString('return new class extends Migration', File::get($expectedMigrationPath)); + + $this->assertStringContainsString('$table->json(\'assets\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->json(\'collections\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->json(\'entries\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->json(\'terms\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->json(\'users\')', File::get($expectedMigrationPath)); + + $this->assertStringContainsString('$table->string(\'asset\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->string(\'collection\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->string(\'entry\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->string(\'term\')', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->string(\'user\')', File::get($expectedMigrationPath)); + + $this->assertFalse(Schema::hasTable('foods')); } /** @test */ public function can_generate_migration_and_ensure_field_is_nullable_if_required_not_set() { - $this->markTestIncomplete(); + TestTime::freeze(); + + Config::set('runway', [ + 'resources' => [ + Food::class => [ + 'name' => 'Food', + 'blueprint' => [ + 'tabs' => [ + 'main' => [ + 'fields' => [ + ['handle' => 'text', 'field' => ['type' => 'text']], + ['handle' => 'entries', 'field' => ['type' => 'entries']], + ], + ], + ], + ], + ], + ], + ]); + + Runway::discoverResources(); + + $this + ->artisan('runway:generate-migrations', [ + 'resource' => 'food', + ]) + ->expectsQuestion('Should we run your migrations?', 'no') + ->execute(); + + $this->assertFileExists( + $expectedMigrationPath = database_path().'/migrations/'.date('Y_m_d_His').'_create_foods_table.php' + ); + + $this->assertStringContainsString('return new class extends Migration', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->text(\'text\')->nullable();', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->json(\'entries\')->nullable();', File::get($expectedMigrationPath)); + + $this->assertFalse(Schema::hasTable('foods')); } /** @test */ public function can_generate_migration_and_ensure_field_is_not_nullable_if_required_set() { - $this->markTestIncomplete(); + TestTime::freeze(); + + Config::set('runway', [ + 'resources' => [ + Food::class => [ + 'name' => 'Food', + 'blueprint' => [ + 'tabs' => [ + 'main' => [ + 'fields' => [ + ['handle' => 'text', 'field' => ['type' => 'text', 'validate' => 'required']], + ['handle' => 'entries', 'field' => ['type' => 'entries', 'validate' => 'required']], + ], + ], + ], + ], + ], + ], + ]); + + Runway::discoverResources(); + + $this + ->artisan('runway:generate-migrations', [ + 'resource' => 'food', + ]) + ->expectsQuestion('Should we run your migrations?', 'no') + ->execute(); + + $this->assertFileExists( + $expectedMigrationPath = database_path().'/migrations/'.date('Y_m_d_His').'_create_foods_table.php' + ); + + $this->assertStringContainsString('return new class extends Migration', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->text(\'text\');', File::get($expectedMigrationPath)); + $this->assertStringContainsString('$table->json(\'entries\');', File::get($expectedMigrationPath)); + + $this->assertFalse(Schema::hasTable('foods')); } } @@ -148,3 +470,12 @@ class Food extends Model protected $fillable = ['name']; } + +class Drink extends Model +{ + use HasRunwayResource; + + protected $table = 'drinks'; + + protected $fillable = ['name']; +}