mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-13 23:54:03 +00:00
Rewrite old tests
This commit is contained in:
parent
64383b4c56
commit
89936187ce
71 changed files with 698 additions and 3203 deletions
|
|
@ -154,6 +154,12 @@ class BootstrapperTest extends TestCase
|
|||
FilesystemTenancyBootstrapper::class
|
||||
]]);
|
||||
|
||||
$old_storage_path = storage_path();
|
||||
$old_storage_facade_roots = [];
|
||||
foreach (config('tenancy.filesystem.disks') as $disk) {
|
||||
$old_storage_facade_roots[$disk] = config("filesystems.disks.{$disk}.root");
|
||||
}
|
||||
|
||||
$tenant1 = Tenant::create();
|
||||
$tenant2 = Tenant::create();
|
||||
|
||||
|
|
@ -176,6 +182,27 @@ class BootstrapperTest extends TestCase
|
|||
tenancy()->initialize($tenant3);
|
||||
$this->assertFalse(Storage::disk('public')->exists('foo'));
|
||||
$this->assertFalse(Storage::disk('public')->exists('abc'));
|
||||
|
||||
// Check suffixing logic
|
||||
$new_storage_path = storage_path();
|
||||
$this->assertEquals($old_storage_path . '/' . config('tenancy.filesystem.suffix_base') . tenant('id'), $new_storage_path);
|
||||
|
||||
foreach (config('tenancy.filesystem.disks') as $disk) {
|
||||
$suffix = config('tenancy.filesystem.suffix_base') . tenant('id');
|
||||
$current_path_prefix = Storage::disk($disk)->getAdapter()->getPathPrefix();
|
||||
|
||||
if ($override = config("tenancy.filesystem.root_override.{$disk}")) {
|
||||
$correct_path_prefix = str_replace('%storage_path%', storage_path(), $override);
|
||||
} else {
|
||||
if ($base = $old_storage_facade_roots[$disk]) {
|
||||
$correct_path_prefix = $base . "/$suffix/";
|
||||
} else {
|
||||
$correct_path_prefix = "$suffix/";
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertSame($correct_path_prefix, $current_path_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
// for queues see QueueTest
|
||||
|
|
|
|||
138
tests/v3/CacheManagerTest.php
Normal file
138
tests/v3/CacheManagerTest.php
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Tests\v3;
|
||||
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Stancl\Tenancy\Database\Models\Tenant;
|
||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||
use Stancl\Tenancy\TenancyBootstrappers\CacheTenancyBootstrapper;
|
||||
use Stancl\Tenancy\Tests\TestCase;
|
||||
|
||||
class CacheManagerTest extends TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
config(['tenancy.bootstrappers' => [
|
||||
CacheTenancyBootstrapper::class,
|
||||
]]);
|
||||
|
||||
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function default_tag_is_automatically_applied()
|
||||
{
|
||||
tenancy()->initialize(Tenant::create());
|
||||
|
||||
$this->assertArrayIsSubset([config('tenancy.cache.tag_base') . tenant('id')], cache()->tags('foo')->getTags()->getNames());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function tags_are_merged_when_array_is_passed()
|
||||
{
|
||||
tenancy()->initialize(Tenant::create());
|
||||
|
||||
$expected = [config('tenancy.cache.tag_base') . tenant('id'), 'foo', 'bar'];
|
||||
$this->assertEquals($expected, cache()->tags(['foo', 'bar'])->getTags()->getNames());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function tags_are_merged_when_string_is_passed()
|
||||
{
|
||||
tenancy()->initialize(Tenant::create());
|
||||
|
||||
$expected = [config('tenancy.cache.tag_base') . tenant('id'), 'foo'];
|
||||
$this->assertEquals($expected, cache()->tags('foo')->getTags()->getNames());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function exception_is_thrown_when_zero_arguments_are_passed_to_tags_method()
|
||||
{
|
||||
tenancy()->initialize(Tenant::create());
|
||||
|
||||
$this->expectException(\Exception::class);
|
||||
cache()->tags();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function exception_is_thrown_when_more_than_one_argument_is_passed_to_tags_method()
|
||||
{
|
||||
tenancy()->initialize(Tenant::create());
|
||||
|
||||
$this->expectException(\Exception::class);
|
||||
cache()->tags(1, 2);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function tags_separate_cache_well_enough()
|
||||
{
|
||||
$tenant1 = Tenant::create();
|
||||
tenancy()->initialize($tenant1);
|
||||
|
||||
cache()->put('foo', 'bar', 1);
|
||||
$this->assertSame('bar', cache()->get('foo'));
|
||||
|
||||
$tenant2 = Tenant::create();
|
||||
tenancy()->initialize($tenant2);
|
||||
|
||||
$this->assertNotSame('bar', cache()->get('foo'));
|
||||
|
||||
cache()->put('foo', 'xyz', 1);
|
||||
$this->assertSame('xyz', cache()->get('foo'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function invoking_the_cache_helper_works()
|
||||
{
|
||||
$tenant1 = Tenant::create();
|
||||
tenancy()->initialize($tenant1);
|
||||
|
||||
cache(['foo' => 'bar'], 1);
|
||||
$this->assertSame('bar', cache('foo'));
|
||||
|
||||
$tenant2 = Tenant::create();
|
||||
tenancy()->initialize($tenant2);
|
||||
|
||||
$this->assertNotSame('bar', cache('foo'));
|
||||
|
||||
cache(['foo' => 'xyz'], 1);
|
||||
$this->assertSame('xyz', cache('foo'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function cache_is_persisted()
|
||||
{
|
||||
$tenant1 = Tenant::create();
|
||||
tenancy()->initialize($tenant1);
|
||||
|
||||
cache(['foo' => 'bar'], 10);
|
||||
$this->assertSame('bar', cache('foo'));
|
||||
|
||||
tenancy()->end();
|
||||
|
||||
tenancy()->initialize($tenant1);
|
||||
$this->assertSame('bar', cache('foo'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function cache_is_persisted_when_reidentification_is_used()
|
||||
{
|
||||
$tenant1 = Tenant::create();
|
||||
$tenant2 = Tenant::create();
|
||||
tenancy()->initialize($tenant1);
|
||||
|
||||
cache(['foo' => 'bar'], 10);
|
||||
$this->assertSame('bar', cache('foo'));
|
||||
|
||||
tenancy()->initialize($tenant2);
|
||||
tenancy()->end();
|
||||
|
||||
tenancy()->initialize($tenant1);
|
||||
$this->assertSame('bar', cache('foo'));
|
||||
}
|
||||
}
|
||||
183
tests/v3/CommandsTest.php
Normal file
183
tests/v3/CommandsTest.php
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Tests\v3;
|
||||
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Stancl\Tenancy\Tests\Etc\ExampleSeeder;
|
||||
use Stancl\Tenancy\Database\Models\Tenant;
|
||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
||||
use Stancl\Tenancy\Events\Listeners\JobPipeline;
|
||||
use Stancl\Tenancy\Events\Listeners\RevertToCentralContext;
|
||||
use Stancl\Tenancy\Events\TenancyEnded;
|
||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||
use Stancl\Tenancy\Events\TenantCreated;
|
||||
use Stancl\Tenancy\Jobs\CreateDatabase;
|
||||
use Stancl\Tenancy\TenancyBootstrappers\DatabaseTenancyBootstrapper;
|
||||
use Stancl\Tenancy\Tests\TestCase;
|
||||
|
||||
class CommandsTest extends TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Event::listen(TenantCreated::class, JobPipeline::make([CreateDatabase::class])->send(function (TenantCreated $event) {
|
||||
return $event->tenant;
|
||||
})->toListener());
|
||||
|
||||
config(['tenancy.bootstrappers' => [
|
||||
DatabaseTenancyBootstrapper::class
|
||||
]]);
|
||||
|
||||
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||
Event::listen(TenancyEnded::class, RevertToCentralContext::class);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function migrate_command_doesnt_change_the_db_connection()
|
||||
{
|
||||
$this->assertFalse(Schema::hasTable('users'));
|
||||
|
||||
$old_connection_name = app(\Illuminate\Database\DatabaseManager::class)->connection()->getName();
|
||||
Artisan::call('tenants:migrate');
|
||||
$new_connection_name = app(\Illuminate\Database\DatabaseManager::class)->connection()->getName();
|
||||
|
||||
$this->assertFalse(Schema::hasTable('users'));
|
||||
$this->assertEquals($old_connection_name, $new_connection_name);
|
||||
$this->assertNotEquals('tenant', $new_connection_name);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function migrate_command_works_without_options()
|
||||
{
|
||||
$tenant = Tenant::create();
|
||||
|
||||
$this->assertFalse(Schema::hasTable('users'));
|
||||
Artisan::call('tenants:migrate');
|
||||
$this->assertFalse(Schema::hasTable('users'));
|
||||
|
||||
tenancy()->initialize($tenant);
|
||||
|
||||
$this->assertTrue(Schema::hasTable('users'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function migrate_command_works_with_tenants_option()
|
||||
{
|
||||
$tenant = Tenant::create();
|
||||
Artisan::call('tenants:migrate', [
|
||||
'--tenants' => [$tenant['id']],
|
||||
]);
|
||||
|
||||
$this->assertFalse(Schema::hasTable('users'));
|
||||
tenancy()->initialize(Tenant::create());
|
||||
$this->assertFalse(Schema::hasTable('users'));
|
||||
|
||||
tenancy()->initialize($tenant);
|
||||
$this->assertTrue(Schema::hasTable('users'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function rollback_command_works()
|
||||
{
|
||||
$tenant = Tenant::create();
|
||||
Artisan::call('tenants:migrate');
|
||||
$this->assertFalse(Schema::hasTable('users'));
|
||||
|
||||
tenancy()->initialize($tenant);
|
||||
|
||||
$this->assertTrue(Schema::hasTable('users'));
|
||||
Artisan::call('tenants:rollback');
|
||||
$this->assertFalse(Schema::hasTable('users'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function seed_command_works()
|
||||
{
|
||||
$this->markTestIncomplete();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function database_connection_is_switched_to_default()
|
||||
{
|
||||
$originalDBName = DB::connection()->getDatabaseName();
|
||||
|
||||
Artisan::call('tenants:migrate');
|
||||
$this->assertSame($originalDBName, DB::connection()->getDatabaseName());
|
||||
|
||||
Artisan::call('tenants:seed', ['--class' => ExampleSeeder::class]);
|
||||
$this->assertSame($originalDBName, DB::connection()->getDatabaseName());
|
||||
|
||||
Artisan::call('tenants:rollback');
|
||||
$this->assertSame($originalDBName, DB::connection()->getDatabaseName());
|
||||
|
||||
$this->run_commands_works();
|
||||
$this->assertSame($originalDBName, DB::connection()->getDatabaseName());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function database_connection_is_switched_to_default_when_tenancy_has_been_initialized()
|
||||
{
|
||||
tenancy()->initialize(Tenant::create());
|
||||
|
||||
$this->database_connection_is_switched_to_default();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function run_commands_works()
|
||||
{
|
||||
$id = Tenant::create()->id;
|
||||
|
||||
Artisan::call('tenants:migrate', ['--tenants' => [$id]]);
|
||||
|
||||
$this->artisan("tenants:run foo --tenants=$id --argument='a=foo' --option='b=bar' --option='c=xyz'")
|
||||
->expectsOutput("User's name is Test command")
|
||||
->expectsOutput('foo')
|
||||
->expectsOutput('xyz');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function install_command_works()
|
||||
{
|
||||
if (! is_dir($dir = app_path('Http'))) {
|
||||
mkdir($dir, 0777, true);
|
||||
}
|
||||
if (! is_dir($dir = base_path('routes'))) {
|
||||
mkdir($dir, 0777, true);
|
||||
}
|
||||
|
||||
$this->artisan('tenancy:install');
|
||||
$this->assertFileExists(base_path('routes/tenant.php'));
|
||||
$this->assertFileExists(base_path('config/tenancy.php'));
|
||||
$this->assertFileExists(database_path('migrations/2019_09_15_000010_create_tenants_table.php'));
|
||||
$this->assertFileExists(database_path('migrations/2019_09_15_000020_create_domains_table.php'));
|
||||
$this->assertDirectoryExists(database_path('migrations/tenant'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function migrate_fresh_command_works()
|
||||
{
|
||||
$tenant = Tenant::create();
|
||||
|
||||
$this->assertFalse(Schema::hasTable('users'));
|
||||
Artisan::call('tenants:migrate-fresh');
|
||||
$this->assertFalse(Schema::hasTable('users'));
|
||||
|
||||
tenancy()->initialize($tenant);
|
||||
|
||||
$this->assertTrue(Schema::hasTable('users'));
|
||||
|
||||
$this->assertFalse(DB::table('users')->exists());
|
||||
DB::table('users')->insert(['name' => 'xxx', 'password' => bcrypt('password'), 'email' => 'foo@bar.xxx']);
|
||||
$this->assertTrue(DB::table('users')->exists());
|
||||
|
||||
// test that db is wiped
|
||||
Artisan::call('tenants:migrate-fresh');
|
||||
$this->assertFalse(DB::table('users')->exists());
|
||||
}
|
||||
}
|
||||
122
tests/v3/DatabaseUsersTest.php
Normal file
122
tests/v3/DatabaseUsersTest.php
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Tests\v3;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Str;
|
||||
use Stancl\Tenancy\Contracts\ManagesDatabaseUsers;
|
||||
use Stancl\Tenancy\Exceptions\TenantDatabaseUserAlreadyExistsException;
|
||||
use Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager;
|
||||
use Stancl\Tenancy\TenantDatabaseManagers\PermissionControlledMySQLDatabaseManager;
|
||||
use Stancl\Tenancy\Database\Models\Tenant;
|
||||
use Stancl\Tenancy\Events\Listeners\JobPipeline;
|
||||
use Stancl\Tenancy\Events\TenantCreated;
|
||||
use Stancl\Tenancy\Jobs\CreateDatabase;
|
||||
use Stancl\Tenancy\Tests\TestCase;
|
||||
|
||||
class DatabaseUsersTest extends TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
config([
|
||||
'tenancy.database_managers.mysql' => PermissionControlledMySQLDatabaseManager::class,
|
||||
'tenancy.database.suffix' => '',
|
||||
'tenancy.template_tenant_connection' => 'mysql',
|
||||
]);
|
||||
|
||||
Event::listen(TenantCreated::class, JobPipeline::make([CreateDatabase::class])->send(function (TenantCreated $event) {
|
||||
return $event->tenant;
|
||||
})->toListener());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function users_are_created_when_permission_controlled_mysql_manager_is_used()
|
||||
{
|
||||
$tenant = new Tenant([
|
||||
'id' => 'foo' . Str::random(10),
|
||||
]);
|
||||
$tenant->database()->makeCredentials();
|
||||
|
||||
/** @var ManagesDatabaseUsers $manager */
|
||||
$manager = $tenant->database()->manager();
|
||||
$this->assertFalse($manager->userExists($tenant->database()->getUsername()));
|
||||
|
||||
$tenant->save();
|
||||
|
||||
$this->assertTrue($manager->userExists($tenant->database()->getUsername()));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function a_tenants_database_cannot_be_created_when_the_user_already_exists()
|
||||
{
|
||||
$username = 'foo' . Str::random(8);
|
||||
$tenant = Tenant::create([
|
||||
'tenancy_db_username' => $username,
|
||||
]);
|
||||
|
||||
/** @var ManagesDatabaseUsers $manager */
|
||||
$manager = $tenant->database()->manager();
|
||||
$this->assertTrue($manager->userExists($tenant->database()->getUsername()));
|
||||
$this->assertTrue($manager->databaseExists($tenant->database()->getName()));
|
||||
|
||||
$this->expectException(TenantDatabaseUserAlreadyExistsException::class);
|
||||
$tenant2 = Tenant::create([
|
||||
'tenancy_db_username' => $username,
|
||||
]);
|
||||
|
||||
/** @var ManagesDatabaseUsers $manager */
|
||||
$manager = $tenant2->database()->manager();
|
||||
// database was not created because of DB transaction
|
||||
$this->assertFalse($manager->databaseExists($tenant2->database()->getName()));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function correct_grants_are_given_to_users()
|
||||
{
|
||||
PermissionControlledMySQLDatabaseManager::$grants = [
|
||||
'ALTER', 'ALTER ROUTINE', 'CREATE',
|
||||
];
|
||||
|
||||
$tenant = Tenant::create([
|
||||
'tenancy_db_username' => $user = 'user' . Str::random(8),
|
||||
]);
|
||||
|
||||
$query = DB::connection('mysql')->select("SHOW GRANTS FOR `{$tenant->database()->getUsername()}`@`{$tenant->database()->connection()['host']}`")[1];
|
||||
$this->assertStringStartsWith('GRANT CREATE, ALTER, ALTER ROUTINE ON', $query->{"Grants for {$user}@mysql"}); // @mysql because that's the hostname within the docker network
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function having_existing_databases_without_users_and_switching_to_permission_controlled_mysql_manager_doesnt_break_existing_dbs()
|
||||
{
|
||||
config([
|
||||
'tenancy.database_managers.mysql' => MySQLDatabaseManager::class,
|
||||
'tenancy.database.suffix' => '',
|
||||
'tenancy.database.template_connection' => 'mysql',
|
||||
]);
|
||||
|
||||
$tenant = Tenant::create([
|
||||
'id' => 'foo' . Str::random(10),
|
||||
]);
|
||||
|
||||
$this->assertTrue($tenant->database()->manager() instanceof MySQLDatabaseManager);
|
||||
|
||||
$tenant = Tenant::create([
|
||||
'id' => 'foo' . Str::random(10),
|
||||
]);
|
||||
|
||||
tenancy()->initialize($tenant); // check if everything works
|
||||
tenancy()->end();
|
||||
|
||||
config(['tenancy.database_managers.mysql' => PermissionControlledMySQLDatabaseManager::class]);
|
||||
|
||||
tenancy()->initialize($tenant); // check if everything works
|
||||
|
||||
$this->assertTrue($tenant->database()->manager() instanceof PermissionControlledMySQLDatabaseManager);
|
||||
$this->assertSame('root', config('database.connections.tenant.username'));
|
||||
}
|
||||
}
|
||||
59
tests/v3/GlobalCacheTest.php
Normal file
59
tests/v3/GlobalCacheTest.php
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Tests\v3;
|
||||
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Stancl\Tenancy\Facades\GlobalCache;
|
||||
use Stancl\Tenancy\Database\Models\Tenant;
|
||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||
use Stancl\Tenancy\TenancyBootstrappers\CacheTenancyBootstrapper;
|
||||
use Stancl\Tenancy\Tests\TestCase;
|
||||
|
||||
class GlobalCacheTest extends TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
config(['tenancy.bootstrappers' => [
|
||||
CacheTenancyBootstrapper::class,
|
||||
]]);
|
||||
|
||||
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function global_cache_manager_stores_data_in_global_cache()
|
||||
{
|
||||
$this->assertSame(null, cache('foo'));
|
||||
GlobalCache::put(['foo' => 'bar'], 1);
|
||||
$this->assertSame('bar', GlobalCache::get('foo'));
|
||||
|
||||
$tenant1 = Tenant::create();
|
||||
tenancy()->initialize($tenant1);
|
||||
$this->assertSame('bar', GlobalCache::get('foo'));
|
||||
|
||||
GlobalCache::put(['abc' => 'xyz'], 1);
|
||||
cache(['def' => 'ghi'], 10);
|
||||
$this->assertSame('ghi', cache('def'));
|
||||
|
||||
tenancy()->end();
|
||||
$this->assertSame('xyz', GlobalCache::get('abc'));
|
||||
$this->assertSame('bar', GlobalCache::get('foo'));
|
||||
$this->assertSame(null, cache('def'));
|
||||
|
||||
$tenant2 = Tenant::create();
|
||||
tenancy()->initialize($tenant2);
|
||||
$this->assertSame('xyz', GlobalCache::get('abc'));
|
||||
$this->assertSame('bar', GlobalCache::get('foo'));
|
||||
$this->assertSame(null, cache('def'));
|
||||
cache(['def' => 'xxx'], 1);
|
||||
$this->assertSame('xxx', cache('def'));
|
||||
|
||||
tenancy()->initialize($tenant1);
|
||||
$this->assertSame('ghi', cache('def'));
|
||||
}
|
||||
}
|
||||
61
tests/v3/RequestDataIdentificationTest.php
Normal file
61
tests/v3/RequestDataIdentificationTest.php
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Tests\v3;
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Stancl\Tenancy\Database\Models\Tenant;
|
||||
use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData;
|
||||
use Stancl\Tenancy\Tests\TestCase;
|
||||
|
||||
class RequestDataIdentificationTest extends TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
config([
|
||||
'tenancy.central_domains' => [
|
||||
'localhost',
|
||||
],
|
||||
]);
|
||||
|
||||
InitializeTenancyByRequestData::$header = 'X-Tenant';
|
||||
InitializeTenancyByRequestData::$queryParameter = 'tenant';
|
||||
|
||||
Route::middleware(InitializeTenancyByRequestData::class)->get('/test', function () {
|
||||
return 'Tenant id: ' . tenant('id');
|
||||
});
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function header_identification_works()
|
||||
{
|
||||
InitializeTenancyByRequestData::$header = 'X-Tenant';
|
||||
$tenant = Tenant::create();
|
||||
$tenant2 = Tenant::create();
|
||||
|
||||
$this
|
||||
->withoutExceptionHandling()
|
||||
->get('test', [
|
||||
'X-Tenant' => $tenant->id,
|
||||
])
|
||||
->assertSee($tenant->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function query_parameter_identification_works()
|
||||
{
|
||||
InitializeTenancyByRequestData::$header = null;
|
||||
InitializeTenancyByRequestData::$queryParameter = 'tenant';
|
||||
|
||||
$tenant = Tenant::create();
|
||||
$tenant2 = Tenant::create();
|
||||
|
||||
$this
|
||||
->withoutExceptionHandling()
|
||||
->get('test?tenant=' . $tenant->id)
|
||||
->assertSee($tenant->id);
|
||||
}
|
||||
}
|
||||
116
tests/v3/TenantAssetTest.php
Normal file
116
tests/v3/TenantAssetTest.php
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Tests\v3;
|
||||
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Stancl\Tenancy\Controllers\TenantAssetsController;
|
||||
use Stancl\Tenancy\Database\Models\Tenant;
|
||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
|
||||
use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData;
|
||||
use Stancl\Tenancy\TenancyBootstrappers\FilesystemTenancyBootstrapper;
|
||||
use Stancl\Tenancy\Tests\TestCase;
|
||||
|
||||
class TenantAssetTest extends TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
config(['tenancy.bootstrappers' => [
|
||||
FilesystemTenancyBootstrapper::class
|
||||
]]);
|
||||
|
||||
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
// Cleanup
|
||||
TenantAssetsController::$tenancyMiddleware = InitializeTenancyByDomain::class;
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function asset_can_be_accessed_using_the_url_returned_by_the_tenant_asset_helper()
|
||||
{
|
||||
TenantAssetsController::$tenancyMiddleware = InitializeTenancyByRequestData::class;
|
||||
|
||||
$tenant = Tenant::create();
|
||||
tenancy()->initialize($tenant);
|
||||
|
||||
$filename = 'testfile' . $this->randomString(10);
|
||||
Storage::disk('public')->put($filename, 'bar');
|
||||
$path = storage_path("app/public/$filename");
|
||||
|
||||
// response()->file() returns BinaryFileResponse whose content is
|
||||
// inaccessible via getContent, so ->assertSee() can't be used
|
||||
$this->assertFileExists($path);
|
||||
$response = $this->get(tenant_asset($filename), [
|
||||
'X-Tenant' => $tenant->id,
|
||||
]);
|
||||
|
||||
$response->assertSuccessful();
|
||||
|
||||
$f = fopen($path, 'r');
|
||||
$content = fread($f, filesize($path));
|
||||
fclose($f);
|
||||
|
||||
$this->assertSame('bar', $content);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function asset_helper_returns_a_link_to_TenantAssetController_when_asset_url_is_null()
|
||||
{
|
||||
config(['app.asset_url' => null]);
|
||||
|
||||
$tenant = Tenant::create();
|
||||
tenancy()->initialize($tenant);
|
||||
|
||||
$this->assertSame(route('stancl.tenancy.asset', ['path' => 'foo']), asset('foo'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function asset_helper_returns_a_link_to_an_external_url_when_asset_url_is_not_null()
|
||||
{
|
||||
config(['app.asset_url' => 'https://an-s3-bucket']);
|
||||
|
||||
$tenant = Tenant::create();
|
||||
tenancy()->initialize($tenant);
|
||||
|
||||
$this->assertSame("https://an-s3-bucket/tenant{$tenant->id}/foo", asset('foo'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function global_asset_helper_returns_the_same_url_regardless_of_tenancy_initialization()
|
||||
{
|
||||
$original = global_asset('foobar');
|
||||
$this->assertSame(asset('foobar'), global_asset('foobar'));
|
||||
|
||||
$tenant = Tenant::create();
|
||||
tenancy()->initialize($tenant);
|
||||
|
||||
$this->assertSame($original, global_asset('foobar'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function asset_helper_tenancy_can_be_disabled()
|
||||
{
|
||||
$original = asset('foo');
|
||||
|
||||
config([
|
||||
'app.asset_url' => null,
|
||||
'tenancy.filesystem.asset_helper_tenancy' => false,
|
||||
]);
|
||||
|
||||
$tenant = Tenant::create();
|
||||
tenancy()->initialize($tenant);
|
||||
|
||||
$this->assertSame($original, asset('foo'));
|
||||
}
|
||||
}
|
||||
34
tests/v3/TenantAwareCommandTest.php
Normal file
34
tests/v3/TenantAwareCommandTest.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Tests\v3;
|
||||
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Stancl\Tenancy\Database\Models\Tenant;
|
||||
use Stancl\Tenancy\Tests\TestCase;
|
||||
|
||||
class TenantAwareCommandTest extends TestCase
|
||||
{
|
||||
/** @test */
|
||||
public function commands_run_globally_are_tenant_aware_and_return_valid_exit_code()
|
||||
{
|
||||
$tenant1 = Tenant::create();
|
||||
$tenant2 = Tenant::create();
|
||||
Artisan::call('tenants:migrate', [
|
||||
'--tenants' => [$tenant1['id'], $tenant2['id']],
|
||||
]);
|
||||
|
||||
$this->artisan('user:add')
|
||||
->assertExitCode(0);
|
||||
|
||||
tenancy()->initialize($tenant1);
|
||||
$this->assertNotEmpty(DB::table('users')->get());
|
||||
tenancy()->end();
|
||||
|
||||
tenancy()->initialize($tenant2);
|
||||
$this->assertNotEmpty(DB::table('users')->get());
|
||||
tenancy()->end();
|
||||
}
|
||||
}
|
||||
144
tests/v3/TenantDatabaseManagerTest.php
Normal file
144
tests/v3/TenantDatabaseManagerTest.php
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Tests\v3;
|
||||
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Stancl\Tenancy\Database\Models\Tenant;
|
||||
use Stancl\Tenancy\DatabaseManager;
|
||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
||||
use Stancl\Tenancy\Events\Listeners\JobPipeline;
|
||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||
use Stancl\Tenancy\Events\TenantCreated;
|
||||
use Stancl\Tenancy\Jobs\CreateDatabase;
|
||||
use Stancl\Tenancy\TenancyBootstrappers\DatabaseTenancyBootstrapper;
|
||||
use Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager;
|
||||
use Stancl\Tenancy\TenantDatabaseManagers\PermissionControlledMySQLDatabaseManager;
|
||||
use Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLDatabaseManager;
|
||||
use Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLSchemaManager;
|
||||
use Stancl\Tenancy\TenantDatabaseManagers\SQLiteDatabaseManager;
|
||||
use Stancl\Tenancy\Tests\TestCase;
|
||||
|
||||
class TenantDatabaseManagerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider database_manager_provider
|
||||
*/
|
||||
public function databases_can_be_created_and_deleted($driver, $databaseManager)
|
||||
{
|
||||
Event::listen(TenantCreated::class, JobPipeline::make([CreateDatabase::class])->send(function (TenantCreated $event) {
|
||||
return $event->tenant;
|
||||
})->toListener());
|
||||
|
||||
config()->set([
|
||||
"tenancy.database_managers.$driver" => $databaseManager,
|
||||
'tenancy.internal_prefix' => 'tenancy_',
|
||||
]);
|
||||
|
||||
$name = 'db' . $this->randomString();
|
||||
|
||||
$this->assertFalse(app($databaseManager)->databaseExists($name));
|
||||
|
||||
$tenant = Tenant::create([
|
||||
'tenancy_db_name' => $name,
|
||||
'tenancy_db_connection' => $driver,
|
||||
]);
|
||||
|
||||
$this->assertTrue(app($databaseManager)->databaseExists($name));
|
||||
app($databaseManager)->deleteDatabase($tenant);
|
||||
$this->assertFalse(app($databaseManager)->databaseExists($name));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function dbs_can_be_created_when_another_driver_is_used_for_the_central_db()
|
||||
{
|
||||
$this->assertSame('central', config('database.default'));
|
||||
|
||||
Event::listen(TenantCreated::class, JobPipeline::make([CreateDatabase::class])->send(function (TenantCreated $event) {
|
||||
return $event->tenant;
|
||||
})->toListener());
|
||||
|
||||
// todo if the prefix is _tenancy_, this blows up. write a tenantmodel test that the prefix can be _tenancy_
|
||||
config(['tenancy.internal_prefix' => 'tenancy_',]);
|
||||
|
||||
$database = 'db' . $this->randomString();
|
||||
|
||||
$this->assertFalse(app(MySQLDatabaseManager::class)->databaseExists($database));
|
||||
Tenant::create([
|
||||
'tenancy_db_name' => $database,
|
||||
'tenancy_db_connection' => 'mysql',
|
||||
]);
|
||||
|
||||
$this->assertTrue(app(MySQLDatabaseManager::class)->databaseExists($database));
|
||||
|
||||
$database = 'db' . $this->randomString();
|
||||
$this->assertFalse(app(PostgreSQLDatabaseManager::class)->databaseExists($database));
|
||||
|
||||
Tenant::create([
|
||||
'tenancy_db_name' => $database,
|
||||
'tenancy_db_connection' => 'pgsql',
|
||||
]);
|
||||
|
||||
$this->assertTrue(app(PostgreSQLDatabaseManager::class)->databaseExists($database));
|
||||
}
|
||||
|
||||
public function database_manager_provider()
|
||||
{
|
||||
return [
|
||||
['mysql', MySQLDatabaseManager::class],
|
||||
['mysql', PermissionControlledMySQLDatabaseManager::class],
|
||||
['sqlite', SQLiteDatabaseManager::class],
|
||||
['pgsql', PostgreSQLDatabaseManager::class],
|
||||
['pgsql', PostgreSQLSchemaManager::class],
|
||||
];
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function db_name_is_prefixed_with_db_path_when_sqlite_is_used()
|
||||
{
|
||||
if (file_exists(database_path('foodb'))) {
|
||||
unlink(database_path('foodb')); // cleanup
|
||||
}
|
||||
config([
|
||||
'database.connections.fooconn.driver' => 'sqlite',
|
||||
'tenancy.internal_prefix' => 'tenancy_',
|
||||
]);
|
||||
|
||||
$tenant = Tenant::create([
|
||||
'tenancy_db_name' => 'foodb',
|
||||
'tenancy_db_connection' => 'fooconn',
|
||||
]);
|
||||
app(DatabaseManager::class)->createTenantConnection($tenant);
|
||||
|
||||
$this->assertSame(config('database.connections.tenant.database'), database_path('foodb'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function schema_manager_uses_schema_to_separate_tenant_dbs()
|
||||
{
|
||||
config([
|
||||
'tenancy.database_managers.pgsql' => \Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLSchemaManager::class,
|
||||
'tenancy.boostrappers' => [
|
||||
DatabaseTenancyBootstrapper::class,
|
||||
],
|
||||
]);
|
||||
|
||||
Event::listen(TenantCreated::class, JobPipeline::make([CreateDatabase::class])->send(function (TenantCreated $event) {
|
||||
return $event->tenant;
|
||||
})->toListener());
|
||||
|
||||
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||
|
||||
$originalDatabaseName = config(['database.connections.pgsql.database']);
|
||||
|
||||
$tenant = Tenant::create([
|
||||
'tenancy_db_connection' => 'pgsql',
|
||||
]);
|
||||
tenancy()->initialize($tenant);
|
||||
|
||||
$this->assertSame($tenant->database()->getName(), config('database.connections.' . config('database.default') . '.schema'));
|
||||
$this->assertSame($originalDatabaseName, config(['database.connections.pgsql.database']));
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ use Stancl\Tenancy\Events\TenantCreated;
|
|||
use Stancl\Tenancy\Tests\TestCase;
|
||||
use Stancl\Tenancy\UniqueIDGenerators\UUIDGenerator;
|
||||
use Stancl\Tenancy\Contracts;
|
||||
use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator;
|
||||
|
||||
class TenantModelTest extends TestCase
|
||||
{
|
||||
|
|
@ -34,7 +35,7 @@ class TenantModelTest extends TestCase
|
|||
|
||||
tenancy()->initialize($tenant);
|
||||
|
||||
$this->assertSame($tenant->id, app(Tenant::class)->id);
|
||||
$this->assertSame($tenant->id, app(Contracts\Tenant::class)->id);
|
||||
|
||||
tenancy()->end();
|
||||
|
||||
|
|
@ -100,10 +101,10 @@ class TenantModelTest extends TestCase
|
|||
$table->bigIncrements('id')->change();
|
||||
});
|
||||
|
||||
config(['tenancy.id_generator' => null]);
|
||||
unset(app()[UniqueIdentifierGenerator::class]);
|
||||
|
||||
$tenant1 = Tenant::create();
|
||||
$tenant2 = Tenant::create();
|
||||
$tenant1 = MyTenant::create();
|
||||
$tenant2 = MyTenant::create();
|
||||
|
||||
$this->assertSame(1, $tenant1->id);
|
||||
$this->assertSame(2, $tenant2->id);
|
||||
|
|
@ -137,6 +138,7 @@ class TenantModelTest extends TestCase
|
|||
class MyTenant extends Tenant
|
||||
{
|
||||
protected $table = 'tenants';
|
||||
public $increments = true;
|
||||
}
|
||||
|
||||
class AnotherTenant extends Model implements Contracts\Tenant
|
||||
|
|
@ -153,4 +155,9 @@ class AnotherTenant extends Model implements Contracts\Tenant
|
|||
{
|
||||
return $this->getAttribute('id');
|
||||
}
|
||||
|
||||
public function run(callable $callback)
|
||||
{
|
||||
$callback();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue