From 3c4d2189dcbef0b38bc3e51f4a57e1152751f945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20=C5=A0tancl?= Date: Tue, 12 May 2020 03:14:08 +0200 Subject: [PATCH] DatabasePreparationTest --- assets/config.php | 23 +-- src/Commands/Seed.php | 8 +- .../MySQLDatabaseManager.php | 6 +- tests/v3/DatabasePreparationTest.php | 136 +++++++++++++++++- 4 files changed, 148 insertions(+), 25 deletions(-) diff --git a/assets/config.php b/assets/config.php index a90e849b..43f9ef1e 100644 --- a/assets/config.php +++ b/assets/config.php @@ -201,7 +201,7 @@ return [ * See the documentation page for each class to * understand which ones you want to enable. */ - 'features' => [ + 'features' => [ // todo test features // Stancl\Tenancy\Features\Timestamps::class, // https://tenancy.samuelstancl.me/docs/v2/features/timestamps/ // Stancl\Tenancy\Features\TenantConfig::class, // https://tenancy.samuelstancl.me/docs/v2/features/tenant-config/ // Stancl\Tenancy\Features\TelescopeTags::class, // https://tenancy.samuelstancl.me/docs/v2/telescope/ @@ -211,32 +211,15 @@ return [ /** * The URL to which users will be redirected when they try to acceess a central route on a tenant domain. */ - 'home_url' => '/app', - - /** - * Should tenant databases be created asynchronously in a queued job. - */ - 'queue_database_creation' => false, // todo make this a static property + 'home_url' => '/app', // todo move this to static 'migration_parameters' => [ '--force' => true, // Set this to true to be able to run migrations in production - // '--path' => [database_path('migrations/tenant')], // If you need to customize paths to tenant migrations + '--path' => [database_path('migrations/tenant')], ], 'seeder_parameters' => [ '--class' => 'DatabaseSeeder', // root seeder class, e.g.: 'DatabaseSeeder' // '--force' => true, ], - - /** - * Should tenant databases be deleted asynchronously in a queued job. - */ - 'queue_database_deletion' => false, - - /** - * Middleware pushed to the global middleware stack. - */ - 'global_middleware' => [ // todo get rid of this - // Stancl\Tenancy\Middleware\InitializeTenancy::class, - ], ]; diff --git a/src/Commands/Seed.php b/src/Commands/Seed.php index a31d0045..ec9bff03 100644 --- a/src/Commands/Seed.php +++ b/src/Commands/Seed.php @@ -6,6 +6,7 @@ namespace Stancl\Tenancy\Commands; use Illuminate\Database\ConnectionResolverInterface; use Illuminate\Database\Console\Seeds\SeedCommand; +use Stancl\Tenancy\Contracts\TenantWithDatabase; use Stancl\Tenancy\DatabaseManager; use Stancl\Tenancy\Events\DatabaseSeeded; use Stancl\Tenancy\Traits\HasATenantsOption; @@ -54,7 +55,12 @@ class Seed extends SeedCommand return; } - tenancy()->all($this->option('tenants'))->each(function ($tenant) { + tenancy() + ->query() + ->when($this->option('tenants'), function ($query) { + $query->whereIn(tenancy()->model()->getTenantKeyName(), $this->option('tenants')); + }) + ->each(function (TenantWithDatabase $tenant) { $this->line("Tenant: {$tenant['id']}"); $tenant->run(function () { diff --git a/src/TenantDatabaseManagers/MySQLDatabaseManager.php b/src/TenantDatabaseManagers/MySQLDatabaseManager.php index 2685b527..569e280c 100644 --- a/src/TenantDatabaseManagers/MySQLDatabaseManager.php +++ b/src/TenantDatabaseManagers/MySQLDatabaseManager.php @@ -9,7 +9,7 @@ use Illuminate\Database\Connection; use Illuminate\Support\Facades\DB; use Stancl\Tenancy\Contracts\Future\CanSetConnection; use Stancl\Tenancy\Contracts\TenantDatabaseManager; -use Stancl\Tenancy\Tenant; +use Stancl\Tenancy\Contracts\TenantWithDatabase; class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection { @@ -36,7 +36,7 @@ class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection $this->connection = $connection; } - public function createDatabase(Tenant $tenant): bool + public function createDatabase(TenantWithDatabase $tenant): bool { $database = $tenant->database()->getName(); $charset = $this->database()->getConfig('charset'); @@ -45,7 +45,7 @@ class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection return $this->database()->statement("CREATE DATABASE `{$database}` CHARACTER SET `$charset` COLLATE `$collation`"); } - public function deleteDatabase(Tenant $tenant): bool + public function deleteDatabase(TenantWithDatabase $tenant): bool { return $this->database()->statement("DROP DATABASE `{$tenant->database()->getName()}`"); } diff --git a/tests/v3/DatabasePreparationTest.php b/tests/v3/DatabasePreparationTest.php index 4bd4834b..053fa9dd 100644 --- a/tests/v3/DatabasePreparationTest.php +++ b/tests/v3/DatabasePreparationTest.php @@ -1 +1,135 @@ -// test DB creation, migration, seeding \ No newline at end of file + 'mysql']); + + Event::listen(TenantCreated::class, JobPipeline::make([CreateDatabase::class])->send(function (TenantCreated $event) { + return $event->tenant; + })->toListener()); + + $tenant = Tenant::create(); + + $this->assertTrue(app(MySQLDatabaseManager::class)->databaseExists($tenant->database()->getName())); + } + + /** @test */ + public function database_can_be_migrated_after_tenant_creation() + { + Event::listen(TenantCreated::class, JobPipeline::make([ + CreateDatabase::class, + MigrateDatabase::class, + ])->send(function (TenantCreated $event) { + return $event->tenant; + })->toListener()); + + $tenant = Tenant::create(); + + $tenant->run(function () { + $this->assertTrue(Schema::hasTable('users')); + }); + } + + /** @test */ + public function database_can_be_seeded_after_tenant_creation() + { + config(['tenancy.seeder_parameters' => [ + '--class' => TestSeeder::class, + ]]); + + Event::listen(TenantCreated::class, JobPipeline::make([ + CreateDatabase::class, + MigrateDatabase::class, + SeedDatabase::class, + ])->send(function (TenantCreated $event) { + return $event->tenant; + })->toListener()); + + $tenant = Tenant::create(); + + $tenant->run(function () { + $this->assertSame('Seeded User', User::first()->name); + }); + } + + /** @test */ + public function custom_job_can_be_added_to_the_pipeline() + { + config(['tenancy.seeder_parameters' => [ + '--class' => TestSeeder::class, + ]]); + + Event::listen(TenantCreated::class, JobPipeline::make([ + CreateDatabase::class, + MigrateDatabase::class, + SeedDatabase::class, + CreateSuperuser::class, + ])->send(function (TenantCreated $event) { + return $event->tenant; + })->toListener()); + + $tenant = Tenant::create(); + + $tenant->run(function () { + $this->assertSame('Foo', User::all()[1]->name); + }); + } +} + +class User extends Authenticable +{ + protected $guarded = []; +} + +class TestSeeder extends Seeder +{ + /** + * Run the database seeds. + * + * @return void + */ + public function run() + { + DB::table('users')->insert([ + 'name' => 'Seeded User', + 'email' => 'seeded@user', + 'password' => bcrypt('password'), + ]); + } +} + +class CreateSuperuser +{ + protected $tenant; + + public function __construct(Tenant $tenant) + { + $this->tenant = $tenant; + } + + public function handle() + { + $this->tenant->run(function () { + User::create(['name' => 'Foo', 'email' => 'foo@bar.com', 'password' => 'secret']); + }); + } +} \ No newline at end of file