mirror of
https://github.com/archtechx/tenancy.git
synced 2026-02-05 14:34:04 +00:00
Merge branch '2.x' into laravel-7-support
This commit is contained in:
commit
ab8de77529
16 changed files with 571 additions and 26 deletions
164
tests/CachedResolverTest.php
Normal file
164
tests/CachedResolverTest.php
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Tests;
|
||||
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Stancl\Tenancy\StorageDrivers\Database\DatabaseStorageDriver;
|
||||
use Stancl\Tenancy\Tenant;
|
||||
|
||||
class CachedResolverTest extends TestCase
|
||||
{
|
||||
public $autoCreateTenant = false;
|
||||
public $autoInitTenancy = false;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (config('tenancy.storage_driver') !== 'db') {
|
||||
$this->markTestSkipped('This test is only relevant for the DB storage driver.');
|
||||
}
|
||||
|
||||
config(['tenancy.storage_drivers.db.cache_store' => null]); // default driver
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function a_query_is_not_made_for_tenant_id_once_domain_is_cached()
|
||||
{
|
||||
$tenant = Tenant::new()
|
||||
->withData(['foo' => 'bar'])
|
||||
->withDomains(['foo.localhost'])
|
||||
->save();
|
||||
|
||||
// query is made
|
||||
$queried = tenancy()->findByDomain('foo.localhost');
|
||||
$this->assertEquals($tenant->data, $queried->data);
|
||||
$this->assertSame($tenant->domains, $queried->domains);
|
||||
|
||||
// cache is set
|
||||
$this->assertEquals($tenant->id, Cache::get('_tenancy_domain_to_id:foo.localhost'));
|
||||
$this->assertEquals($tenant->data, Cache::get('_tenancy_id_to_data:' . $tenant->id));
|
||||
$this->assertSame($tenant->domains, Cache::get('_tenancy_id_to_domains:' . $tenant->id));
|
||||
|
||||
// query is not made
|
||||
DatabaseStorageDriver::getCentralConnection()->enableQueryLog();
|
||||
$cached = tenancy()->findByDomain('foo.localhost');
|
||||
$this->assertEquals($tenant->data, $cached->data);
|
||||
$this->assertSame($tenant->domains, $cached->domains);
|
||||
$this->assertSame([], DatabaseStorageDriver::getCentralConnection()->getQueryLog());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function a_query_is_not_made_for_tenant_once_id_is_cached()
|
||||
{
|
||||
$tenant = Tenant::new()
|
||||
->withData(['foo' => 'bar'])
|
||||
->withDomains(['foo.localhost'])
|
||||
->save();
|
||||
|
||||
// query is made
|
||||
$queried = tenancy()->find($tenant->id);
|
||||
$this->assertEquals($tenant->data, $queried->data);
|
||||
$this->assertSame($tenant->domains, $queried->domains);
|
||||
|
||||
// cache is set
|
||||
$this->assertEquals($tenant->data, Cache::get('_tenancy_id_to_data:' . $tenant->id));
|
||||
$this->assertSame($tenant->domains, Cache::get('_tenancy_id_to_domains:' . $tenant->id));
|
||||
|
||||
// query is not made
|
||||
DatabaseStorageDriver::getCentralConnection()->enableQueryLog();
|
||||
$cached = tenancy()->find($tenant->id);
|
||||
$this->assertEquals($tenant->data, $cached->data);
|
||||
$this->assertSame($tenant->domains, $cached->domains);
|
||||
$this->assertSame([], DatabaseStorageDriver::getCentralConnection()->getQueryLog());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function modifying_tenant_domains_invalidates_the_cached_domain_to_id_mapping()
|
||||
{
|
||||
$tenant = Tenant::new()
|
||||
->withDomains(['foo.localhost', 'bar.localhost'])
|
||||
->save();
|
||||
|
||||
// queried
|
||||
$this->assertSame($tenant->id, tenancy()->findByDomain('foo.localhost')->id);
|
||||
$this->assertSame($tenant->id, tenancy()->findByDomain('bar.localhost')->id);
|
||||
|
||||
// assert cache set
|
||||
$this->assertSame($tenant->id, Cache::get('_tenancy_domain_to_id:foo.localhost'));
|
||||
$this->assertSame($tenant->id, Cache::get('_tenancy_domain_to_id:bar.localhost'));
|
||||
|
||||
$tenant
|
||||
->removeDomains(['foo.localhost', 'bar.localhost'])
|
||||
->addDomains(['xyz.localhost'])
|
||||
->save();
|
||||
|
||||
// assert neither domain is cached
|
||||
$this->assertSame(null, Cache::get('_tenancy_domain_to_id:foo.localhost'));
|
||||
$this->assertSame(null, Cache::get('_tenancy_domain_to_id:bar.localhost'));
|
||||
$this->assertSame(null, Cache::get('_tenancy_domain_to_id:xyz.localhost'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function modifying_tenants_data_invalidates_tenant_data_cache()
|
||||
{
|
||||
$tenant = Tenant::new()->withData(['foo' => 'bar'])->save();
|
||||
|
||||
// cache record is set
|
||||
$this->assertSame('bar', tenancy()->find($tenant->id)->get('foo'));
|
||||
$this->assertSame('bar', Cache::get('_tenancy_id_to_data:' . $tenant->id)['foo']);
|
||||
|
||||
// cache record is invalidated
|
||||
$tenant->set('foo', 'xyz');
|
||||
$this->assertSame(null, Cache::get('_tenancy_id_to_data:' . $tenant->id));
|
||||
|
||||
// cache record is set
|
||||
$this->assertSame('xyz', tenancy()->find($tenant->id)->get('foo'));
|
||||
$this->assertSame('xyz', Cache::get('_tenancy_id_to_data:' . $tenant->id)['foo']);
|
||||
|
||||
// cache record is invalidated
|
||||
$tenant->foo = 'abc';
|
||||
$tenant->save();
|
||||
$this->assertSame(null, Cache::get('_tenancy_id_to_data:' . $tenant->id));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function modifying_tenants_domains_invalidates_tenant_domain_cache()
|
||||
{
|
||||
$tenant = Tenant::new()
|
||||
->withData(['foo' => 'bar'])
|
||||
->withDomains(['foo.localhost'])
|
||||
->save();
|
||||
|
||||
// cache record is set
|
||||
$this->assertSame(['foo.localhost'], tenancy()->find($tenant->id)->domains);
|
||||
$this->assertSame(['foo.localhost'], Cache::get('_tenancy_id_to_domains:' . $tenant->id));
|
||||
|
||||
// cache record is invalidated
|
||||
$tenant->addDomains(['bar.localhost'])->save();
|
||||
$this->assertEquals(null, Cache::get('_tenancy_id_to_domains:' . $tenant->id));
|
||||
|
||||
$this->assertEquals(['foo.localhost', 'bar.localhost'], tenancy()->find($tenant->id)->domains);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function deleting_a_tenant_invalidates_all_caches()
|
||||
{
|
||||
$tenant = Tenant::new()
|
||||
->withData(['foo' => 'bar'])
|
||||
->withDomains(['foo.localhost'])
|
||||
->save();
|
||||
|
||||
tenancy()->findByDomain('foo.localhost');
|
||||
$this->assertEquals($tenant->id, Cache::get('_tenancy_domain_to_id:foo.localhost'));
|
||||
$this->assertEquals($tenant->data, Cache::get('_tenancy_id_to_data:' . $tenant->id));
|
||||
$this->assertEquals(['foo.localhost'], Cache::get('_tenancy_id_to_domains:' . $tenant->id));
|
||||
|
||||
$tenant->delete();
|
||||
$this->assertEquals(null, Cache::get('_tenancy_domain_to_id:foo.localhost'));
|
||||
$this->assertEquals(null, Cache::get('_tenancy_id_to_data:' . $tenant->id));
|
||||
$this->assertEquals(null, Cache::get('_tenancy_id_to_domains:' . $tenant->id));
|
||||
}
|
||||
}
|
||||
143
tests/DatabaseSchemaManagerTest.php
Normal file
143
tests/DatabaseSchemaManagerTest.php
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Tests;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Stancl\Tenancy\Tenant;
|
||||
|
||||
class DatabaseSchemaManagerTest extends TestCase
|
||||
{
|
||||
public $autoInitTenancy = false;
|
||||
|
||||
protected function getEnvironmentSetUp($app)
|
||||
{
|
||||
parent::getEnvironmentSetUp($app);
|
||||
|
||||
$app['config']->set([
|
||||
'database.default' => 'pgsql',
|
||||
'database.connections.pgsql.database' => 'main',
|
||||
'database.connections.pgsql.schema' => 'public',
|
||||
'tenancy.database.based_on' => null,
|
||||
'tenancy.database.suffix' => '',
|
||||
'tenancy.database.separate_by' => 'schema',
|
||||
'tenancy.database_managers.pgsql' => \Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLSchemaManager::class,
|
||||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function reconnect_method_works()
|
||||
{
|
||||
$old_connection_name = app(\Illuminate\Database\DatabaseManager::class)->connection()->getName();
|
||||
|
||||
tenancy()->init('test.localhost');
|
||||
|
||||
app(\Stancl\Tenancy\DatabaseManager::class)->reconnect();
|
||||
|
||||
$new_connection_name = app(\Illuminate\Database\DatabaseManager::class)->connection()->getName();
|
||||
|
||||
$this->assertSame($old_connection_name, $new_connection_name);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function the_default_db_is_used_when_based_on_is_null()
|
||||
{
|
||||
config(['database.default' => 'pgsql']);
|
||||
|
||||
$this->assertSame('pgsql', config('database.default'));
|
||||
config([
|
||||
'database.connections.pgsql.foo' => 'bar',
|
||||
'tenancy.database.based_on' => null,
|
||||
]);
|
||||
|
||||
tenancy()->init('test.localhost');
|
||||
|
||||
$this->assertSame('tenant', config('database.default'));
|
||||
$this->assertSame('bar', config('database.connections.' . config('database.default') . '.foo'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function make_sure_using_schema_connection()
|
||||
{
|
||||
$tenant = tenancy()->create(['schema.localhost']);
|
||||
tenancy()->init('schema.localhost');
|
||||
|
||||
$this->assertSame($tenant->getDatabaseName(), config('database.connections.' . config('database.default') . '.schema'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function databases_are_separated_using_schema_and_not_database()
|
||||
{
|
||||
tenancy()->create('foo.localhost');
|
||||
tenancy()->init('foo.localhost');
|
||||
$this->assertSame('tenant', config('database.default'));
|
||||
$this->assertSame('main', config('database.connections.tenant.database'));
|
||||
|
||||
$schema1 = config('database.connections.' . config('database.default') . '.schema');
|
||||
$database1 = config('database.connections.' . config('database.default') . '.database');
|
||||
|
||||
tenancy()->create('bar.localhost');
|
||||
tenancy()->init('bar.localhost');
|
||||
$this->assertSame('tenant', config('database.default'));
|
||||
$this->assertSame('main', config('database.connections.tenant.database'));
|
||||
|
||||
$schema2 = config('database.connections.' . config('database.default') . '.schema');
|
||||
$database2 = config('database.connections.' . config('database.default') . '.database');
|
||||
|
||||
$this->assertSame($database1, $database2);
|
||||
$this->assertNotSame($schema1, $schema2);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function schemas_are_separated()
|
||||
{
|
||||
// copied from DataSeparationTest
|
||||
|
||||
$tenant1 = Tenant::create('tenant1.localhost');
|
||||
$tenant2 = Tenant::create('tenant2.localhost');
|
||||
\Artisan::call('tenants:migrate', [
|
||||
'--tenants' => [$tenant1['id'], $tenant2['id']],
|
||||
]);
|
||||
|
||||
tenancy()->init('tenant1.localhost');
|
||||
User::create([
|
||||
'name' => 'foo',
|
||||
'email' => 'foo@bar.com',
|
||||
'email_verified_at' => now(),
|
||||
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||
'remember_token' => Str::random(10),
|
||||
]);
|
||||
$this->assertSame('foo', User::first()->name);
|
||||
|
||||
tenancy()->init('tenant2.localhost');
|
||||
$this->assertSame(null, User::first());
|
||||
|
||||
User::create([
|
||||
'name' => 'xyz',
|
||||
'email' => 'xyz@bar.com',
|
||||
'email_verified_at' => now(),
|
||||
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||
'remember_token' => Str::random(10),
|
||||
]);
|
||||
|
||||
$this->assertSame('xyz', User::first()->name);
|
||||
$this->assertSame('xyz@bar.com', User::first()->email);
|
||||
|
||||
tenancy()->init('tenant1.localhost');
|
||||
$this->assertSame('foo', User::first()->name);
|
||||
$this->assertSame('foo@bar.com', User::first()->email);
|
||||
|
||||
$tenant3 = Tenant::create('tenant3.localhost');
|
||||
\Artisan::call('tenants:migrate', [
|
||||
'--tenants' => [$tenant1['id'], $tenant3['id']],
|
||||
]);
|
||||
|
||||
tenancy()->init('tenant3.localhost');
|
||||
$this->assertSame(null, User::first());
|
||||
|
||||
tenancy()->init('tenant1.localhost');
|
||||
\DB::table('users')->where('id', 1)->update(['name' => 'xxx']);
|
||||
$this->assertSame('xxx', User::first()->name);
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ use Stancl\Tenancy\Jobs\QueuedTenantDatabaseDeleter;
|
|||
use Stancl\Tenancy\Tenant;
|
||||
use Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager;
|
||||
use Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLDatabaseManager;
|
||||
use Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLSchemaManager;
|
||||
use Stancl\Tenancy\TenantDatabaseManagers\SQLiteDatabaseManager;
|
||||
|
||||
class TenantDatabaseManagerTest extends TestCase
|
||||
|
|
@ -78,6 +79,7 @@ class TenantDatabaseManagerTest extends TestCase
|
|||
['mysql', MySQLDatabaseManager::class],
|
||||
['sqlite', SQLiteDatabaseManager::class],
|
||||
['pgsql', PostgreSQLDatabaseManager::class],
|
||||
['pgsql', PostgreSQLSchemaManager::class],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,12 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
|||
Redis::connection('tenancy')->flushdb();
|
||||
Redis::connection('cache')->flushdb();
|
||||
|
||||
$originalConnection = config('database.default');
|
||||
$this->loadMigrationsFrom([
|
||||
'--path' => realpath(__DIR__ . '/../assets/migrations'),
|
||||
'--database' => 'central',
|
||||
]);
|
||||
config(['database.default' => 'sqlite']); // fix issue caused by loadMigrationsFrom
|
||||
config(['database.default' => $originalConnection]); // fix issue caused by loadMigrationsFrom
|
||||
|
||||
if ($this->autoCreateTenant) {
|
||||
$this->createTenant();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue