diff --git a/tests/DatabaseCacheBootstrapperTest.php b/tests/DatabaseCacheBootstrapperTest.php index d6895ce4..87ca91ca 100644 --- a/tests/DatabaseCacheBootstrapperTest.php +++ b/tests/DatabaseCacheBootstrapperTest.php @@ -4,30 +4,18 @@ declare(strict_types=1); use Stancl\Tenancy\Bootstrappers\DatabaseCacheBootstrapper; use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper; -use Illuminate\Support\Facades\Event; -use Stancl\Tenancy\Events\TenantCreated; -use Stancl\JobPipeline\JobPipeline; -use Stancl\Tenancy\Jobs\CreateDatabase; use Stancl\Tenancy\Tests\Etc\Tenant; use Illuminate\Support\Facades\DB; -use Stancl\Tenancy\Events\TenancyInitialized; -use Stancl\Tenancy\Listeners\BootstrapTenancy; -use Stancl\Tenancy\Events\TenancyEnded; -use Stancl\Tenancy\Listeners\RevertToCentralContext; -use Illuminate\Support\Facades\Schema; -use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Cache; -beforeEach(function () { - Event::listen( - TenantCreated::class, - JobPipeline::make([CreateDatabase::class])->send(function (TenantCreated $event) { - return $event->tenant; - })->toListener() - ); +use function Stancl\Tenancy\Tests\withBootstrapping; +use function Stancl\Tenancy\Tests\withCacheTables; +use function Stancl\Tenancy\Tests\withTenantDatabases; - Event::listen(TenancyInitialized::class, BootstrapTenancy::class); - Event::listen(TenancyEnded::class, RevertToCentralContext::class); +beforeEach(function () { + withBootstrapping(); + withCacheTables(); + withTenantDatabases(true); DatabaseCacheBootstrapper::$stores = null; @@ -47,66 +35,38 @@ afterEach(function () { }); test('DatabaseCacheBootstrapper switches the database cache store connections correctly', function () { - // Original connections (store and lock) are 'central' in the config expect(config('cache.stores.database.connection'))->toBe('central'); expect(config('cache.stores.database.lock_connection'))->toBe('central'); - // The actual connection used by the cache store is 'central' expect(Cache::store()->getConnection()->getName())->toBe('central'); - // Cache locks also use the 'central' connection expect(Cache::lock('foo')->getConnectionName())->toBe('central'); tenancy()->initialize(Tenant::create()); - // Initializing tenancy should make both connections 'tenant' expect(config('cache.stores.database.connection'))->toBe('tenant'); expect(config('cache.stores.database.lock_connection'))->toBe('tenant'); - // The actual connection used by the cache store and locks is now 'tenant' - // Purging the database cache store forces the CacheManager to resolve a new instance of - // the database store, using the connection names specified in the config ('tenant') expect(Cache::store()->getConnection()->getName())->toBe('tenant'); expect(Cache::lock('foo')->getConnectionName())->toBe('tenant'); tenancy()->end(); - // Ending tenancy should change both connections back to the original ('central') expect(config('cache.stores.database.connection'))->toBe('central'); expect(config('cache.stores.database.lock_connection'))->toBe('central'); - // The actual connection used by the cache store and the cache locks is now 'central' again expect(Cache::store()->getConnection()->getName())->toBe('central'); expect(Cache::lock('foo')->getConnectionName())->toBe('central'); }); test('cache is separated correctly when using DatabaseCacheBootstrapper', function() { - // DB query for verifying that the cache is stored - // in the cache table of the current DB connection - // under the passed key (the key in the DB is prefixed by the default cache prefix). - $getCacheUsingDbQuery = function (string $cacheKey) { - // Prefix the cache key with the default cache prefix - $databaseCacheKey = config('cache.prefix') . $cacheKey; + // We need the prefix later for lower-level assertions. Let's store it + // once now and reuse this variable rather than re-fetching it to make + // it clear that the scoping does NOT come from a prefix change. - return DB::selectOne("SELECT * FROM `cache` WHERE `key` = '{$databaseCacheKey}'")?->value; - }; - - // Create the cache table in the central DB - Schema::create('cache', function (Blueprint $table) { - $table->string('key')->primary(); - $table->mediumText('value'); - $table->integer('expiration'); - }); + $cachePrefix = config('cache.prefix'); + $getCacheUsingDbQuery = fn (string $cacheKey) => + DB::selectOne("SELECT * FROM `cache` WHERE `key` = '{$cachePrefix}{$cacheKey}'")?->value; $tenant = Tenant::create(); $tenant2 = Tenant::create(); - // Create the cache table in tenant DBs - // With DatabaseCacheBootstrapper, cache will be saved in these tenant DBs instead of the central DB - tenancy()->runForMultiple([$tenant, $tenant2], function () { - Schema::create('cache', function (Blueprint $table) { - $table->string('key')->primary(); - $table->mediumText('value'); - $table->integer('expiration'); - }); - }); - // Write to cache in central context cache()->set('foo', 'central'); expect(Cache::get('foo'))->toBe('central'); @@ -118,19 +78,16 @@ test('cache is separated correctly when using DatabaseCacheBootstrapper', functi // Central cache doesn't leak to tenant context expect(Cache::has('foo'))->toBeFalse(); - // Verify that the 'foo' cache key doesn't exist in the tenant's DB using a direct DB query expect($getCacheUsingDbQuery('foo'))->toBeNull(); cache()->set('foo', 'bar'); expect(Cache::get('foo'))->toBe('bar'); - // Verify that the 'foo' cache key is 'bar' using a direct DB query expect($getCacheUsingDbQuery('foo'))->toContain('bar'); tenancy()->initialize($tenant2); // Assert one tenant's cache doesn't leak to another tenant expect(Cache::has('foo'))->toBeFalse(); - // The 'foo' cache key in another tenant's database shouldn't exist expect($getCacheUsingDbQuery('foo'))->toBeNull(); cache()->set('foo', 'xyz'); @@ -151,7 +108,6 @@ test('cache is separated correctly when using DatabaseCacheBootstrapper', functi }); test('DatabaseCacheBootstrapper auto-detects all database driver stores by default', function() { - // Configure multiple stores with different drivers config([ 'cache.stores.database' => [ 'driver' => 'database', diff --git a/tests/Pest.php b/tests/Pest.php index 198ee815..a4517f09 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -7,12 +7,22 @@ use Stancl\Tenancy\Tests\TestCase; use Stancl\JobPipeline\JobPipeline; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Schema; +use Stancl\Tenancy\Events\TenancyEnded; +use Stancl\Tenancy\Events\TenancyInitialized; use Stancl\Tenancy\Jobs\CreateDatabase; use Stancl\Tenancy\Events\TenantCreated; use Stancl\Tenancy\Jobs\MigrateDatabase; +use Stancl\Tenancy\Listeners\BootstrapTenancy; +use Stancl\Tenancy\Listeners\RevertToCentralContext; uses(TestCase::class)->in(__DIR__); +function withBootstrapping() +{ + Event::listen(TenancyInitialized::class, BootstrapTenancy::class); + Event::listen(TenancyEnded::class, RevertToCentralContext::class); +} + function withTenantDatabases(bool $migrate = false) { Event::listen(TenantCreated::class, JobPipeline::make($migrate