1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2026-05-06 23:44:03 +00:00
tenancy/tests/AutomaticModeTest.php
Samuel Štancl 60dd5226c4
[4.x] Add Tenancy::reinitialize() method (#1449)
Some bootstrappers read attributes of the tenant during bootstrap() but
don't respond to changes made to the tenant afterwards.

Therefore, when making changes to the tenant that'd affect the behavior
of a bootstrapper, it's necessary to reinitialize tenancy (if it matters
that changes are reflected immediately). This adds a convenience helper
for that purpose.
2026-04-08 19:21:43 +02:00

157 lines
4.2 KiB
PHP

<?php
declare(strict_types=1);
use Illuminate\Support\Facades\Event;
use Stancl\Tenancy\Contracts\TenancyBootstrapper;
use Stancl\Tenancy\Events\TenancyEnded;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Tests\Etc\Tenant;
use function Stancl\Tenancy\Tests\pest;
use function Stancl\Tenancy\Tests\withTenantDatabases;
beforeEach(function () {
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
Event::listen(TenancyEnded::class, RevertToCentralContext::class);
});
test('context is switched to tenant when initializing tenancy and reverted when ending tenancy', function () {
config(['tenancy.bootstrappers' => [
MyBootstrapper::class,
]]);
$tenant = Tenant::create([
'id' => 'acme',
]);
tenancy()->initialize($tenant);
expect(app('tenancy_initialized_for_tenant'))->toBe('acme');
tenancy()->end();
expect(app('tenancy_ended'))->toBe(true);
});
test('context is switched when tenancy is reinitialized', function () {
config(['tenancy.bootstrappers' => [
MyBootstrapper::class,
]]);
$tenant = Tenant::create([
'id' => 'acme',
]);
tenancy()->initialize($tenant);
expect(app('tenancy_initialized_for_tenant'))->toBe('acme');
$tenant2 = Tenant::create([
'id' => 'foobar',
]);
tenancy()->initialize($tenant2);
expect(app('tenancy_initialized_for_tenant'))->toBe('foobar');
});
test('central helper runs callbacks in the central state', function () {
withTenantDatabases();
tenancy()->initialize($tenant = Tenant::create());
tenancy()->central(function () {
expect(tenant())->toBe(null);
});
expect(tenant())->toBe($tenant);
});
test('central helper returns the value from the callback', function () {
withTenantDatabases();
tenancy()->initialize(Tenant::create());
pest()->assertSame('foo', tenancy()->central(function () {
return 'foo';
}));
});
test('central helper reverts back to tenant context', function () {
withTenantDatabases();
tenancy()->initialize($tenant = Tenant::create());
tenancy()->central(function () {
//
});
expect(tenant())->toBe($tenant);
});
test('central helper doesnt change tenancy state when called in central context', function () {
expect(tenancy()->initialized)->toBeFalse();
expect(tenant())->toBeNull();
tenancy()->central(function () {
//
});
expect(tenancy()->initialized)->toBeFalse();
expect(tenant())->toBeNull();
});
test('reinitialize method does nothing in the central context', function () {
expect(tenancy()->initialized)->toBe(false);
expect(fn () => tenancy()->reinitialize())->not()->toThrow(\Throwable::class);
expect(tenancy()->initialized)->toBe(false);
});
test('reinitialize method runs bootstrappers again for the current tenant', function () {
config(['tenancy.bootstrappers' => [
ReinitBootstrapper::class,
]]);
tenancy()->initialize($tenant = Tenant::create(['reinit_bootstrapper_key' => 'foo']));
expect(tenant()->getKey())->toBe($tenant->getKey());
expect(app('tenancy_reinit_bootstrapper_key'))->toBe('foo');
$tenant->update(['reinit_bootstrapper_key' => 'bar']);
// Unchanged until we reinitialize...
expect(app('tenancy_reinit_bootstrapper_key'))->toBe('foo');
tenancy()->reinitialize();
expect(tenant()->getKey())->toBe($tenant->getKey());
expect(app('tenancy_reinit_bootstrapper_key'))->toBe('bar');
});
class MyBootstrapper implements TenancyBootstrapper
{
public function bootstrap(\Stancl\Tenancy\Contracts\Tenant $tenant): void
{
app()->instance('tenancy_initialized_for_tenant', $tenant->getTenantKey());
}
public function revert(): void
{
app()->instance('tenancy_ended', true);
}
}
class ReinitBootstrapper implements TenancyBootstrapper
{
public function bootstrap(\Stancl\Tenancy\Contracts\Tenant $tenant): void
{
app()->instance('tenancy_reinit_bootstrapper_key', $tenant->getAttribute('reinit_bootstrapper_key'));
}
public function revert(): void
{
app()->instance('tenancy_reinit_bootstrapper_key', null);
}
}