From 3f347ecaf695a4bdc4873aa655fff3d8d12556fd Mon Sep 17 00:00:00 2001 From: Abrar Ahmad Date: Sat, 2 Jul 2022 21:52:47 +0500 Subject: [PATCH] Fix tests in PR #884 PHPUnit to Pest Converter (#885) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fixed tests, remove method duplications, restore necessary inner classes * Update CommandsTest.php * temporary checks run on `shift-64622` on branch. * fixed `TestSeeder` class not resolved * fixed messed up names * removed `uses` from individual files and add it in `Pest` * extract tests to helpers * use pest dataset * Update AutomaticModeTest.php * newline * todo convention * resolve reviews * added `// todo@tests` * remove shift branch from CI workflow Co-authored-by: Samuel Ć tancl --- tests/AutomaticModeTest.php | 45 ++-- tests/BootstrapperTest.php | 3 - tests/CacheManagerTest.php | 2 - tests/CachedTenantResolverTest.php | 2 - ...edDomainAndSubdomainIdentificationTest.php | 9 +- tests/CommandsTest.php | 66 +++--- tests/DatabasePreparationTest.php | 40 ++-- tests/DatabaseUsersTest.php | 2 - tests/DomainTest.php | 9 +- tests/Etc/TestSeeder.php | 23 ++ tests/EventListenerTest.php | 13 +- tests/GlobalCacheTest.php | 3 +- tests/MaintenanceModeTest.php | 8 +- tests/PathIdentificationTest.php | 2 - tests/Pest.php | 41 +--- tests/QueueTest.php | 76 ++++--- tests/RequestDataIdentificationTest.php | 2 - tests/ResourceSyncingTest.php | 204 ++++++++++------- tests/ScopeSessionsTest.php | 2 - tests/SingleDatabaseTenancyTest.php | 207 +++++++++++------- tests/SubdomainTest.php | 9 +- tests/TenantAssetTest.php | 5 - tests/TenantAwareCommandTest.php | 2 - tests/TenantDatabaseManagerTest.php | 3 - tests/TenantModelTest.php | 47 ++-- tests/TenantUserImpersonationTest.php | 16 +- tests/UniversalRouteTest.php | 27 ++- 27 files changed, 500 insertions(+), 368 deletions(-) create mode 100644 tests/Etc/TestSeeder.php diff --git a/tests/AutomaticModeTest.php b/tests/AutomaticModeTest.php index a263aa74..7b5d5ded 100644 --- a/tests/AutomaticModeTest.php +++ b/tests/AutomaticModeTest.php @@ -3,35 +3,24 @@ 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; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { Event::listen(TenancyInitialized::class, BootstrapTenancy::class); Event::listen(TenancyEnded::class, RevertToCentralContext::class); }); test('context is switched when tenancy is initialized', function () { - config(['tenancy.bootstrappers' => [ - MyBootstrapper::class, - ]]); - - $tenant = Tenant::create([ - 'id' => 'acme', - ]); - - tenancy()->initialize($tenant); - - expect(app('tenancy_initialized_for_tenant'))->toBe('acme'); + contextIsSwitchedWhenTenancyInitialized(); }); test('context is reverted when tenancy is ended', function () { - $this->context_is_switched_when_tenancy_is_initialized(); + contextIsSwitchedWhenTenancyInitialized(); tenancy()->end(); @@ -100,13 +89,31 @@ test('central helper doesnt change tenancy state when called in central context' expect(tenant())->toBeNull(); }); -// Helpers -function bootstrap(\Stancl\Tenancy\Contracts\Tenant $tenant) +// todo@tests +function contextIsSwitchedWhenTenancyInitialized() { - app()->instance('tenancy_initialized_for_tenant', $tenant->getTenantKey()); + config(['tenancy.bootstrappers' => [ + MyBootstrapper::class, + ]]); + + $tenant = Tenant::create([ + 'id' => 'acme', + ]); + + tenancy()->initialize($tenant); + + expect(app('tenancy_initialized_for_tenant'))->toBe('acme'); } -function revert() +class MyBootstrapper implements TenancyBootstrapper { - app()->instance('tenancy_ended', true); + public function bootstrap(\Stancl\Tenancy\Contracts\Tenant $tenant) + { + app()->instance('tenancy_initialized_for_tenant', $tenant->getTenantKey()); + } + + public function revert() + { + app()->instance('tenancy_ended', true); + } } diff --git a/tests/BootstrapperTest.php b/tests/BootstrapperTest.php index 90a98056..929c4e47 100644 --- a/tests/BootstrapperTest.php +++ b/tests/BootstrapperTest.php @@ -22,8 +22,6 @@ use Stancl\Tenancy\Bootstrappers\RedisTenancyBootstrapper; use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper; use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { Event::listen( TenantCreated::class, @@ -184,7 +182,6 @@ test('filesystem data is separated', function () { expect($new_storage_path)->toEqual($expected_storage_path); }); -// Helpers function getDiskPrefix(string $disk): string { /** @var FilesystemAdapter $disk */ diff --git a/tests/CacheManagerTest.php b/tests/CacheManagerTest.php index 19bfa566..7b34a7df 100644 --- a/tests/CacheManagerTest.php +++ b/tests/CacheManagerTest.php @@ -8,8 +8,6 @@ use Stancl\Tenancy\Events\TenancyInitialized; use Stancl\Tenancy\Listeners\BootstrapTenancy; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { config(['tenancy.bootstrappers' => [ CacheTenancyBootstrapper::class, diff --git a/tests/CachedTenantResolverTest.php b/tests/CachedTenantResolverTest.php index f8d1dbe1..e386ad57 100644 --- a/tests/CachedTenantResolverTest.php +++ b/tests/CachedTenantResolverTest.php @@ -6,8 +6,6 @@ use Illuminate\Support\Facades\DB; use Stancl\Tenancy\Resolvers\DomainTenantResolver; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - afterEach(function () { DomainTenantResolver::$shouldCache = false; }); diff --git a/tests/CombinedDomainAndSubdomainIdentificationTest.php b/tests/CombinedDomainAndSubdomainIdentificationTest.php index 6234a92b..db01ef99 100644 --- a/tests/CombinedDomainAndSubdomainIdentificationTest.php +++ b/tests/CombinedDomainAndSubdomainIdentificationTest.php @@ -3,9 +3,9 @@ declare(strict_types=1); use Illuminate\Support\Facades\Route; +use Stancl\Tenancy\Database\Concerns\HasDomains; use Stancl\Tenancy\Middleware\InitializeTenancyByDomainOrSubdomain; - -uses(Stancl\Tenancy\Tests\TestCase::class); +use Stancl\Tenancy\Database\Models; beforeEach(function () { Route::group([ @@ -60,3 +60,8 @@ test('tenant can be identified by domain', function () { expect(tenancy()->initialized)->toBeTrue(); expect(tenant('id'))->toBe('acme'); }); + +class CombinedTenant extends Models\Tenant +{ + use HasDomains; +} diff --git a/tests/CommandsTest.php b/tests/CommandsTest.php index 5f23d427..8ad67538 100644 --- a/tests/CommandsTest.php +++ b/tests/CommandsTest.php @@ -17,8 +17,6 @@ use Stancl\Tenancy\Listeners\RevertToCentralContext; use Stancl\Tenancy\Tests\Etc\ExampleSeeder; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { Event::listen(TenantCreated::class, JobPipeline::make([CreateDatabase::class])->send(function (TenantCreated $event) { return $event->tenant; @@ -117,41 +115,21 @@ test('rollback command works', function () { expect(Schema::hasTable('users'))->toBeFalse(); }); -test('seed command works', function () { - $this->markTestIncomplete(); -}); +// Incomplete test +test('seed command works'); test('database connection is switched to default', function () { - $originalDBName = DB::connection()->getDatabaseName(); - - Artisan::call('tenants:migrate'); - expect(DB::connection()->getDatabaseName())->toBe($originalDBName); - - Artisan::call('tenants:seed', ['--class' => ExampleSeeder::class]); - expect(DB::connection()->getDatabaseName())->toBe($originalDBName); - - Artisan::call('tenants:rollback'); - expect(DB::connection()->getDatabaseName())->toBe($originalDBName); - - $this->run_commands_works(); - expect(DB::connection()->getDatabaseName())->toBe($originalDBName); + databaseConnectionSwitchedToDefault(); }); test('database connection is switched to default when tenancy has been initialized', function () { tenancy()->initialize(Tenant::create()); - $this->database_connection_is_switched_to_default(); + databaseConnectionSwitchedToDefault(); }); -test('run commands works', function () { - $id = Tenant::create()->getTenantKey(); - - 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('run command works', function () { + runCommandWorks(); }); test('install command works', function () { @@ -200,3 +178,35 @@ test('run command with array of tenants works', function () { ->expectsOutput('Tenant: ' . $tenantId1) ->expectsOutput('Tenant: ' . $tenantId2); }); + +// todo@tests +function runCommandWorks(): void +{ + $id = Tenant::create()->getTenantKey(); + + Artisan::call('tenants:migrate', ['--tenants' => [$id]]); + + test()->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'); +} + +// todo@tests +function databaseConnectionSwitchedToDefault() +{ + $originalDBName = DB::connection()->getDatabaseName(); + + Artisan::call('tenants:migrate'); + expect(DB::connection()->getDatabaseName())->toBe($originalDBName); + + Artisan::call('tenants:seed', ['--class' => ExampleSeeder::class]); + expect(DB::connection()->getDatabaseName())->toBe($originalDBName); + + Artisan::call('tenants:rollback'); + expect(DB::connection()->getDatabaseName())->toBe($originalDBName); + + runCommandWorks(); + + expect(DB::connection()->getDatabaseName())->toBe($originalDBName); +} diff --git a/tests/DatabasePreparationTest.php b/tests/DatabasePreparationTest.php index 251b14fb..64fa1e0f 100644 --- a/tests/DatabasePreparationTest.php +++ b/tests/DatabasePreparationTest.php @@ -2,7 +2,6 @@ declare(strict_types=1); -use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Schema; use Stancl\JobPipeline\JobPipeline; @@ -12,8 +11,8 @@ use Stancl\Tenancy\Jobs\MigrateDatabase; use Stancl\Tenancy\Jobs\SeedDatabase; use Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager; use Stancl\Tenancy\Tests\Etc\Tenant; - -uses(Stancl\Tenancy\Tests\TestCase::class); +use Illuminate\Foundation\Auth\User as Authenticable; +use Stancl\Tenancy\Tests\Etc\TestSeeder; test('database can be created after tenant creation', function () { config(['tenancy.database.template_tenant_connection' => 'mysql']); @@ -86,29 +85,24 @@ test('custom job can be added to the pipeline', function () { }); }); -// Helpers -/** - * Run the database seeds. - * - * @return void - */ -function run() +class User extends Authenticable { - DB::table('users')->insert([ - 'name' => 'Seeded User', - 'email' => 'seeded@user', - 'password' => bcrypt('password'), - ]); + protected $guarded = []; } -function __construct(Tenant $tenant) +class CreateSuperuser { - test()->tenant = $tenant; -} + protected $tenant; -function handle() -{ - test()->tenant->run(function () { - User::create(['name' => 'Foo', 'email' => 'foo@bar.com', 'password' => 'secret']); - }); + 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']); + }); + } } diff --git a/tests/DatabaseUsersTest.php b/tests/DatabaseUsersTest.php index b2c1cea8..93ac7ec3 100644 --- a/tests/DatabaseUsersTest.php +++ b/tests/DatabaseUsersTest.php @@ -18,8 +18,6 @@ use Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager; use Stancl\Tenancy\TenantDatabaseManagers\PermissionControlledMySQLDatabaseManager; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { config([ 'tenancy.database.managers.mysql' => PermissionControlledMySQLDatabaseManager::class, diff --git a/tests/DomainTest.php b/tests/DomainTest.php index 981e02c0..907681ff 100644 --- a/tests/DomainTest.php +++ b/tests/DomainTest.php @@ -3,14 +3,14 @@ declare(strict_types=1); use Illuminate\Support\Facades\Route; +use Stancl\Tenancy\Database\Concerns\HasDomains; +use Stancl\Tenancy\Database\Models; use Stancl\Tenancy\Database\Models\Domain; use Stancl\Tenancy\Exceptions\DomainOccupiedByOtherTenantException; use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedOnDomainException; use Stancl\Tenancy\Middleware\InitializeTenancyByDomain; use Stancl\Tenancy\Resolvers\DomainTenantResolver; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { Route::group([ 'middleware' => InitializeTenancyByDomain::class, @@ -97,3 +97,8 @@ test('domains are always lowercase', function () { expect(Domain::first()->domain)->toBe('capitals'); }); + +class DomainTenant extends Models\Tenant +{ + use HasDomains; +} diff --git a/tests/Etc/TestSeeder.php b/tests/Etc/TestSeeder.php new file mode 100644 index 00000000..3412948e --- /dev/null +++ b/tests/Etc/TestSeeder.php @@ -0,0 +1,23 @@ +insert([ + 'name' => 'Seeded User', + 'email' => 'seeded@user', + 'password' => bcrypt('password'), + ]); + } +} diff --git a/tests/EventListenerTest.php b/tests/EventListenerTest.php index 62f8edf7..66dcedc8 100644 --- a/tests/EventListenerTest.php +++ b/tests/EventListenerTest.php @@ -17,10 +17,9 @@ use Stancl\Tenancy\Events\UpdatingDomain; use Stancl\Tenancy\Jobs\CreateDatabase; use Stancl\Tenancy\Jobs\MigrateDatabase; use Stancl\Tenancy\Listeners\BootstrapTenancy; +use Stancl\Tenancy\Listeners\QueueableListener; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - test('listeners can be synchronous', function () { Queue::fake(); Event::listen(TenantCreated::class, FooListener::class); @@ -180,8 +179,12 @@ test('database is not migrated if creation is disabled', function () { expect($this->hasFailed())->toBeFalse(); }); -// Helpers -function handle() +class FooListener extends QueueableListener { - app()->instance('foo', 'bar'); + public static $shouldQueue = false; + + public function handle() + { + app()->instance('foo', 'bar'); + } } diff --git a/tests/GlobalCacheTest.php b/tests/GlobalCacheTest.php index db7d4417..8a13395c 100644 --- a/tests/GlobalCacheTest.php +++ b/tests/GlobalCacheTest.php @@ -11,8 +11,6 @@ use Stancl\Tenancy\Listeners\BootstrapTenancy; use Stancl\Tenancy\Listeners\RevertToCentralContext; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { config(['tenancy.bootstrappers' => [ CacheTenancyBootstrapper::class, @@ -51,3 +49,4 @@ test('global cache manager stores data in global cache', function () { tenancy()->initialize($tenant1); expect(cache('def'))->toBe('ghi'); }); + diff --git a/tests/MaintenanceModeTest.php b/tests/MaintenanceModeTest.php index 0cf0e54d..dace6c51 100644 --- a/tests/MaintenanceModeTest.php +++ b/tests/MaintenanceModeTest.php @@ -2,14 +2,13 @@ declare(strict_types=1); +use Stancl\Tenancy\Database\Concerns\MaintenanceMode; use Symfony\Component\HttpKernel\Exception\HttpException; use Illuminate\Support\Facades\Route; use Stancl\Tenancy\Middleware\CheckTenantForMaintenanceMode; use Stancl\Tenancy\Middleware\InitializeTenancyByDomain; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - test('tenant can be in maintenance mode', function () { Route::get('/foo', function () { return 'bar'; @@ -31,3 +30,8 @@ test('tenant can be in maintenance mode', function () { $this->withoutExceptionHandling() ->get('http://acme.localhost/foo'); }); + +class MaintenanceTenant extends Tenant +{ + use MaintenanceMode; +} diff --git a/tests/PathIdentificationTest.php b/tests/PathIdentificationTest.php index 8ad93918..4cd793d7 100644 --- a/tests/PathIdentificationTest.php +++ b/tests/PathIdentificationTest.php @@ -9,8 +9,6 @@ use Stancl\Tenancy\Middleware\InitializeTenancyByPath; use Stancl\Tenancy\Resolvers\PathTenantResolver; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { PathTenantResolver::$tenantParameterName = 'tenant'; diff --git a/tests/Pest.php b/tests/Pest.php index 2e0dcbfb..9325cf53 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,42 +1,3 @@ in('Etc', 'Features'); - -/* -|-------------------------------------------------------------------------- -| Test Case -|-------------------------------------------------------------------------- -| -| The closure you provide to your test functions is always bound to a specific PHPUnit test -| case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may -| need to change it using the "uses()" function to bind a different classes or traits. -| -*/ - -/** @link https://pestphp.com/docs/underlying-test-case */ - -/* -|-------------------------------------------------------------------------- -| Expectations -|-------------------------------------------------------------------------- -| -| When you're writing tests, you often need to check that values meet certain conditions. The -| "expect()" function gives you access to a set of "expectations" methods that you can use -| to assert different things. Of course, you may extend the Expectation API at any time. -| -*/ - -/** @link https://pestphp.com/docs/expectations#custom-expectations */ - -/* -|-------------------------------------------------------------------------- -| Functions -|-------------------------------------------------------------------------- -| -| While Pest is very powerful out-of-the-box, you may have some testing code specific to your -| project that you don't want to repeat in every file. Here you can also expose helpers as -| global functions to help you to reduce the number of lines of code in your test files. -| -*/ - -/** @link https://pestphp.com/docs/helpers */ +uses(Stancl\Tenancy\Tests\TestCase::class)->in(__DIR__); diff --git a/tests/QueueTest.php b/tests/QueueTest.php index dfa5df59..1e662645 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -2,6 +2,11 @@ declare(strict_types=1); +use Illuminate\Bus\Queueable; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; use Illuminate\Support\Str; use Spatie\Valuestore\Valuestore; use Illuminate\Support\Facades\DB; @@ -22,8 +27,6 @@ use Stancl\Tenancy\Listeners\RevertToCentralContext; use Stancl\Tenancy\Bootstrappers\QueueTenancyBootstrapper; use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { config([ 'tenancy.bootstrappers' => [ @@ -78,11 +81,6 @@ test('tenant id is not passed to central queues', function () { }); }); -/** - * - * @testWith [true] - * [false] - */ test('tenancy is initialized inside queues', function (bool $shouldEndTenancy) { withTenantDatabases(); withFailedJobs(); @@ -114,13 +112,8 @@ test('tenancy is initialized inside queues', function (bool $shouldEndTenancy) { $tenant->run(function () use ($user) { expect($user->fresh()->name)->toBe('Bar'); }); -}); +})->with([true, false]);; -/** - * - * @testWith [true] - * [false] - */ test('tenancy is initialized when retrying jobs', function (bool $shouldEndTenancy) { if (! Str::startsWith(app()->version(), '8')) { $this->markTestSkipped('queue:retry tenancy is only supported in Laravel 8'); @@ -163,7 +156,7 @@ test('tenancy is initialized when retrying jobs', function (bool $shouldEndTenan $tenant->run(function () use ($user) { expect($user->fresh()->name)->toBe('Bar'); }); -}); +})->with([true, false]); test('the tenant used by the job doesnt change when the current tenant changes', function () { $tenant1 = Tenant::create([ @@ -186,7 +179,6 @@ test('the tenant used by the job doesnt change when the current tenant changes', expect($this->valuestore->get('tenant_id'))->toBe('The current tenant id is: acme'); }); -// Helpers function createValueStore(): void { $valueStorePath = __DIR__ . '/Etc/tmp/queuetest.json'; @@ -235,27 +227,39 @@ function withTenantDatabases() })->toListener()); } -function __construct(Valuestore $valuestore, User $user = null) +class TestJob implements ShouldQueue { - test()->valuestore = $valuestore; - test()->user = $user; + use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + + /** @var Valuestore */ + protected $valuestore; + + /** @var User|null */ + protected $user; + + public function __construct(Valuestore $valuestore, User $user = null) + { + $this->valuestore = $valuestore; + $this->user = $user; + } + + public function handle() + { + if ($this->valuestore->get('shouldFail')) { + $this->valuestore->put('shouldFail', false); + + throw new Exception('failing'); + } + + if ($this->user) { + assert($this->user->getConnectionName() === 'tenant'); + } + + $this->valuestore->put('tenant_id', 'The current tenant id is: ' . tenant('id')); + + if ($userName = $this->valuestore->get('userName')) { + $this->user->update(['name' => $userName]); + } + } } -function handle() -{ - if (test()->valuestore->get('shouldFail')) { - test()->valuestore->put('shouldFail', false); - - throw new Exception('failing'); - } - - if (test()->user) { - assert(test()->user->getConnectionName() === 'tenant'); - } - - test()->valuestore->put('tenant_id', 'The current tenant id is: ' . tenant('id')); - - if ($userName = test()->valuestore->get('userName')) { - test()->user->update(['name' => $userName]); - } -} diff --git a/tests/RequestDataIdentificationTest.php b/tests/RequestDataIdentificationTest.php index 46b880b4..81bdda53 100644 --- a/tests/RequestDataIdentificationTest.php +++ b/tests/RequestDataIdentificationTest.php @@ -6,8 +6,6 @@ use Illuminate\Support\Facades\Route; use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { config([ 'tenancy.central_domains' => [ diff --git a/tests/ResourceSyncingTest.php b/tests/ResourceSyncingTest.php index 3b863ae7..bc068d52 100644 --- a/tests/ResourceSyncingTest.php +++ b/tests/ResourceSyncingTest.php @@ -10,6 +10,10 @@ use Illuminate\Support\Facades\Queue; use Illuminate\Support\Str; use Stancl\JobPipeline\JobPipeline; use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper; +use Stancl\Tenancy\Contracts\Syncable; +use Stancl\Tenancy\Contracts\SyncMaster; +use Stancl\Tenancy\Database\Concerns\CentralConnection; +use Stancl\Tenancy\Database\Concerns\ResourceSyncing; use Stancl\Tenancy\Database\Models\TenantPivot; use Stancl\Tenancy\DatabaseConfig; use Stancl\Tenancy\Events\SyncedResourceChangedInForeignDatabase; @@ -24,8 +28,6 @@ use Stancl\Tenancy\Listeners\RevertToCentralContext; use Stancl\Tenancy\Listeners\UpdateSyncedResource; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { config(['tenancy.bootstrappers' => [ DatabaseTenancyBootstrapper::class, @@ -45,7 +47,7 @@ beforeEach(function () { UpdateSyncedResource::$shouldQueue = false; // global state cleanup Event::listen(SyncedResourceSaved::class, UpdateSyncedResource::class); - $this->artisan('migrate', [ + test()->artisan('migrate', [ '--path' => [ __DIR__ . '/Etc/synced_resource_migrations', __DIR__ . '/Etc/synced_resource_migrations/users', @@ -81,7 +83,7 @@ test('only the synced columns are updated in the central db', function () { ]); $tenant = ResourceTenant::create(); - migrateTenants(); + migrateTenantsResource(); tenancy()->initialize($tenant); @@ -125,40 +127,11 @@ test('only the synced columns are updated in the central db', function () { }); test('creating the resource in tenant database creates it in central database and creates the mapping', function () { - // Assert no user in central DB - expect(ResourceUser::all())->toHaveCount(0); - - $tenant = ResourceTenant::create(); - migrateTenants(); - - tenancy()->initialize($tenant); - - // Create the same user in tenant DB - ResourceUser::create([ - 'global_id' => 'acme', - 'name' => 'John Doe', - 'email' => 'john@localhost', - 'password' => 'secret', - 'role' => 'commenter', // unsynced - ]); - - tenancy()->end(); - - // Asset user was created - expect(CentralUser::first()->global_id)->toBe('acme'); - expect(CentralUser::first()->role)->toBe('commenter'); - - // Assert mapping was created - expect(CentralUser::first()->tenants)->toHaveCount(1); - - // Assert role change doesn't cascade - CentralUser::first()->update(['role' => 'central superadmin']); - tenancy()->initialize($tenant); - expect(ResourceUser::first()->role)->toBe('commenter'); + creatingResourceInTenantDatabaseCreatesAndMapInCentralDatabase(); }); test('trying to update synced resources from central context using tenant models results in an exception', function () { - $this->creating_the_resource_in_tenant_database_creates_it_in_central_database_and_creates_the_mapping(); + creatingResourceInTenantDatabaseCreatesAndMapInCentralDatabase(); tenancy()->end(); expect(tenancy()->initialized)->toBeFalse(); @@ -179,7 +152,7 @@ test('attaching a tenant to the central resource triggers a pull from the tenant $tenant = ResourceTenant::create([ 'id' => 't1', ]); - migrateTenants(); + migrateTenantsResource(); $tenant->run(function () { expect(ResourceUser::all())->toHaveCount(0); @@ -192,7 +165,7 @@ test('attaching a tenant to the central resource triggers a pull from the tenant }); }); -test('attaching users to tenants d o e s n o t d o a n y t h i n g', function () { +test('attaching users to tenants does not do anything', function () { $centralUser = CentralUser::create([ 'global_id' => 'acme', 'name' => 'John Doe', @@ -204,7 +177,7 @@ test('attaching users to tenants d o e s n o t d o a n y t h i n g', function () $tenant = ResourceTenant::create([ 'id' => 't1', ]); - migrateTenants(); + migrateTenantsResource(); $tenant->run(function () { expect(ResourceUser::all())->toHaveCount(0); @@ -239,7 +212,7 @@ test('resources are synced only to workspaces that have the resource', function $t3 = ResourceTenant::create([ 'id' => 't3', ]); - migrateTenants(); + migrateTenantsResource(); $centralUser->tenants()->attach('t1'); $centralUser->tenants()->attach('t2'); @@ -261,7 +234,7 @@ test('resources are synced only to workspaces that have the resource', function }); }); -test('when a resource exists in other tenant dbs but is c r e a t e d in a tenant db the synced columns are updated in the other dbs', function () { +test('when a resource exists in other tenant dbs but is created in a tenant db the synced columns are updated in the other dbs', function () { // create shared resource $centralUser = CentralUser::create([ 'global_id' => 'acme', @@ -277,7 +250,7 @@ test('when a resource exists in other tenant dbs but is c r e a t e d in a tenan $t2 = ResourceTenant::create([ 'id' => 't2', ]); - migrateTenants(); + migrateTenantsResource(); // Copy (cascade) user to t1 DB $centralUser->tenants()->attach('t1'); @@ -325,7 +298,7 @@ test('the synced columns are updated in other tenant dbs where the resource exis $t3 = ResourceTenant::create([ 'id' => 't3', ]); - migrateTenants(); + migrateTenantsResource(); // Copy (cascade) user to t1 DB $centralUser->tenants()->attach('t1'); @@ -380,7 +353,7 @@ test('when the resource doesnt exist in the tenant db non synced columns will ca 'id' => 't1', ]); - migrateTenants(); + migrateTenantsResource(); $centralUser->tenants()->attach('t1'); @@ -394,7 +367,7 @@ test('when the resource doesnt exist in the central db non synced columns will b 'id' => 't1', ]); - migrateTenants(); + migrateTenantsResource(); $t1->run(function () { ResourceUser::create([ @@ -416,7 +389,7 @@ test('the listener can be queued', function () { 'id' => 't1', ]); - migrateTenants(); + migrateTenantsResource(); Queue::assertNothingPushed(); @@ -455,7 +428,7 @@ test('an event is fired for all touched resources', function () { $t3 = ResourceTenant::create([ 'id' => 't3', ]); - migrateTenants(); + migrateTenantsResource(); // Copy (cascade) user to t1 DB $centralUser->tenants()->attach('t1'); @@ -529,8 +502,42 @@ test('an event is fired for all touched resources', function () { }); }); -// Helpers -function migrateTenants() +// todo@tests +function creatingResourceInTenantDatabaseCreatesAndMapInCentralDatabase() +{ + // Assert no user in central DB + expect(ResourceUser::all())->toHaveCount(0); + + $tenant = ResourceTenant::create(); + migrateTenantsResource(); + + tenancy()->initialize($tenant); + + // Create the same user in tenant DB + ResourceUser::create([ + 'global_id' => 'acme', + 'name' => 'John Doe', + 'email' => 'john@localhost', + 'password' => 'secret', + 'role' => 'commenter', // unsynced + ]); + + tenancy()->end(); + + // Asset user was created + expect(CentralUser::first()->global_id)->toBe('acme'); + expect(CentralUser::first()->role)->toBe('commenter'); + + // Assert mapping was created + expect(CentralUser::first()->tenants)->toHaveCount(1); + + // Assert role change doesn't cascade + CentralUser::first()->update(['role' => 'central superadmin']); + tenancy()->initialize($tenant); + expect(ResourceUser::first()->role)->toBe('commenter'); +} + +function migrateTenantsResource() { test()->artisan('tenants:migrate', [ '--path' => __DIR__ . '/Etc/synced_resource_migrations/users', @@ -538,43 +545,88 @@ function migrateTenants() ])->assertExitCode(0); } -function users() +class ResourceTenant extends Tenant { - return test()->belongsToMany(CentralUser::class, 'tenant_users', 'tenant_id', 'global_user_id', 'id', 'global_id') - ->using(TenantPivot::class); + public function users() + { + return $this->belongsToMany(CentralUser::class, 'tenant_users', 'tenant_id', 'global_user_id', 'id', 'global_id') + ->using(TenantPivot::class); + } } -function tenants(): BelongsToMany +class CentralUser extends Model implements SyncMaster { - return test()->belongsToMany(ResourceTenant::class, 'tenant_users', 'global_user_id', 'tenant_id', 'global_id') - ->using(TenantPivot::class); + use ResourceSyncing, CentralConnection; + + protected $guarded = []; + public $timestamps = false; + public $table = 'users'; + + public function tenants(): BelongsToMany + { + return $this->belongsToMany(ResourceTenant::class, 'tenant_users', 'global_user_id', 'tenant_id', 'global_id') + ->using(TenantPivot::class); + } + + public function getTenantModelName(): string + { + return ResourceUser::class; + } + + public function getGlobalIdentifierKey() + { + return $this->getAttribute($this->getGlobalIdentifierKeyName()); + } + + public function getGlobalIdentifierKeyName(): string + { + return 'global_id'; + } + + public function getCentralModelName(): string + { + return static::class; + } + + public function getSyncedAttributeNames(): array + { + return [ + 'name', + 'password', + 'email', + ]; + } } -function getTenantModelName(): string +class ResourceUser extends Model implements Syncable { - return ResourceUser::class; -} + use ResourceSyncing; -function getGlobalIdentifierKey() -{ - return test()->getAttribute(test()->getGlobalIdentifierKeyName()); -} + protected $table = 'users'; + protected $guarded = []; + public $timestamps = false; -function getGlobalIdentifierKeyName(): string -{ - return 'global_id'; -} + public function getGlobalIdentifierKey() + { + return $this->getAttribute($this->getGlobalIdentifierKeyName()); + } -function getCentralModelName(): string -{ - return CentralUser::class; -} + public function getGlobalIdentifierKeyName(): string + { + return 'global_id'; + } -function getSyncedAttributeNames(): array -{ - return [ - 'name', - 'password', - 'email', - ]; + public function getCentralModelName(): string + { + return CentralUser::class; + } + + public function getSyncedAttributeNames(): array + { + return [ + 'name', + 'password', + 'email', + ]; + } } diff --git a/tests/ScopeSessionsTest.php b/tests/ScopeSessionsTest.php index 9e8eedb0..b1b6a05e 100644 --- a/tests/ScopeSessionsTest.php +++ b/tests/ScopeSessionsTest.php @@ -11,8 +11,6 @@ use Stancl\Tenancy\Middleware\InitializeTenancyBySubdomain; use Stancl\Tenancy\Middleware\ScopeSessions; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { Route::group([ 'middleware' => [StartSession::class, InitializeTenancyBySubdomain::class, ScopeSessions::class], diff --git a/tests/SingleDatabaseTenancyTest.php b/tests/SingleDatabaseTenancyTest.php index 19f2813c..be0afa91 100644 --- a/tests/SingleDatabaseTenancyTest.php +++ b/tests/SingleDatabaseTenancyTest.php @@ -2,13 +2,15 @@ declare(strict_types=1); +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\QueryException; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Validator; +use Stancl\Tenancy\Database\Concerns\BelongsToPrimaryModel; use Stancl\Tenancy\Database\Concerns\BelongsToTenant; - -uses(Stancl\Tenancy\Tests\TestCase::class); +use Stancl\Tenancy\Database\Concerns\HasScopedValidationRules; +use Stancl\Tenancy\Tests\Etc\Tenant as TestTenant; beforeEach(function () { BelongsToTenant::$tenantIdColumn = 'tenant_id'; @@ -35,52 +37,11 @@ beforeEach(function () { }); test('primary models are scoped to the current tenant', function () { - // acme context - tenancy()->initialize($acme = Tenant::create([ - 'id' => 'acme', - ])); - - $post = Post::create(['text' => 'Foo']); - - expect($post->tenant_id)->toBe('acme'); - expect($post->tenant->id)->toBe('acme'); - - $post = Post::first(); - - expect($post->tenant_id)->toBe('acme'); - expect($post->tenant->id)->toBe('acme'); - - // ====================================== - // foobar context - tenancy()->initialize($foobar = Tenant::create([ - 'id' => 'foobar', - ])); - - $post = Post::create(['text' => 'Bar']); - - expect($post->tenant_id)->toBe('foobar'); - expect($post->tenant->id)->toBe('foobar'); - - $post = Post::first(); - - expect($post->tenant_id)->toBe('foobar'); - expect($post->tenant->id)->toBe('foobar'); - - // ====================================== - // acme context again - - tenancy()->initialize($acme); - - $post = Post::first(); - expect($post->tenant_id)->toBe('acme'); - expect($post->tenant->id)->toBe('acme'); - - // Assert foobar models are inaccessible in acme context - expect(Post::count())->toBe(1); + primaryModelsScopedToCurrentTenant(); }); test('primary models are not scoped in the central context', function () { - $this->primary_models_are_scoped_to_the_current_tenant(); + primaryModelsScopedToCurrentTenant(); tenancy()->end(); @@ -88,32 +49,11 @@ test('primary models are not scoped in the central context', function () { }); test('secondary models are scoped to the current tenant when accessed via primary model', function () { - // acme context - tenancy()->initialize($acme = Tenant::create([ - 'id' => 'acme', - ])); - - $post = Post::create(['text' => 'Foo']); - $post->comments()->create(['text' => 'Comment text']); - - // ================ - // foobar context - tenancy()->initialize($foobar = Tenant::create([ - 'id' => 'foobar', - ])); - - $post = Post::create(['text' => 'Bar']); - $post->comments()->create(['text' => 'Comment text 2']); - - // ================ - // acme context again - tenancy()->initialize($acme); - expect(Post::count())->toBe(1); - expect(Post::first()->comments->count())->toBe(1); + secondaryModelsAreScopedToCurrentTenant(); }); -test('secondary models are n o t scoped to the current tenant when accessed directly', function () { - $this->secondary_models_are_scoped_to_the_current_tenant_when_accessed_via_primary_model(); +test('secondary models are not scoped to the current tenant when accessed directly', function () { + secondaryModelsAreScopedToCurrentTenant(); // We're in acme context expect(tenant('id'))->toBe('acme'); @@ -121,7 +61,7 @@ test('secondary models are n o t scoped to the current tenant when accessed dire expect(Comment::count())->toBe(2); }); -test('secondary models a r e scoped to the current tenant when accessed directly a n d p a r e n t r e l a t i o n s h i p t r a i t i s u s e d', function () { +test('secondary models a r e scoped to the current tenant when accessed directly and parent relationship traitis used', function () { $acme = Tenant::create([ 'id' => 'acme', ]); @@ -153,8 +93,8 @@ test('secondary models a r e scoped to the current tenant when accessed directly expect(ScopedComment::count())->toBe(2); }); -test('secondary models are n o t scoped in the central context', function () { - $this->secondary_models_are_scoped_to_the_current_tenant_when_accessed_via_primary_model(); +test('secondary models are not scoped in the central context', function () { + secondaryModelsAreScopedToCurrentTenant(); tenancy()->end(); @@ -287,23 +227,128 @@ test('the model returned by the tenant helper has unique and exists validation r expect($existsFails)->toBeFalse(); }); -// Helpers -function comments() +// todo@tests +function primaryModelsScopedToCurrentTenant() { - return test()->hasMany(Comment::class); + // acme context + tenancy()->initialize($acme = Tenant::create([ + 'id' => 'acme', + ])); + + $post = Post::create(['text' => 'Foo']); + + expect($post->tenant_id)->toBe('acme'); + expect($post->tenant->id)->toBe('acme'); + + $post = Post::first(); + + expect($post->tenant_id)->toBe('acme'); + expect($post->tenant->id)->toBe('acme'); + + // ====================================== + // foobar context + tenancy()->initialize($foobar = Tenant::create([ + 'id' => 'foobar', + ])); + + $post = Post::create(['text' => 'Bar']); + + expect($post->tenant_id)->toBe('foobar'); + expect($post->tenant->id)->toBe('foobar'); + + $post = Post::first(); + + expect($post->tenant_id)->toBe('foobar'); + expect($post->tenant->id)->toBe('foobar'); + + // ====================================== + // acme context again + + tenancy()->initialize($acme); + + $post = Post::first(); + expect($post->tenant_id)->toBe('acme'); + expect($post->tenant->id)->toBe('acme'); + + // Assert foobar models are inaccessible in acme context + expect(Post::count())->toBe(1); } -function scoped_comments() +// todo@tests +function secondaryModelsAreScopedToCurrentTenant() { - return test()->hasMany(Comment::class); + // acme context + tenancy()->initialize($acme = Tenant::create([ + 'id' => 'acme', + ])); + + $post = Post::create(['text' => 'Foo']); + $post->comments()->create(['text' => 'Comment text']); + + // ================ + // foobar context + tenancy()->initialize($foobar = Tenant::create([ + 'id' => 'foobar', + ])); + + $post = Post::create(['text' => 'Bar']); + $post->comments()->create(['text' => 'Comment text 2']); + + // ================ + // acme context again + tenancy()->initialize($acme); + expect(Post::count())->toBe(1); + expect(Post::first()->comments->count())->toBe(1); } -function post() +class Tenant extends TestTenant { - return test()->belongsTo(Post::class); + use HasScopedValidationRules; } -function getRelationshipToPrimaryModel(): string +class Post extends Model { - return 'post'; + use BelongsToTenant; + + protected $guarded = []; + public $timestamps = false; + + public function comments() + { + return $this->hasMany(Comment::class); + } + + public function scoped_comments() + { + return $this->hasMany(Comment::class); + } +} + +class Comment extends Model +{ + protected $guarded = []; + public $timestamps = false; + + public function post() + { + return $this->belongsTo(Post::class); + } +} + +class ScopedComment extends Comment +{ + use BelongsToPrimaryModel; + + protected $table = 'comments'; + + public function getRelationshipToPrimaryModel(): string + { + return 'post'; + } +} + +class GlobalResource extends Model +{ + protected $guarded = []; + public $timestamps = false; } diff --git a/tests/SubdomainTest.php b/tests/SubdomainTest.php index 2b9d8350..6cbe1f05 100644 --- a/tests/SubdomainTest.php +++ b/tests/SubdomainTest.php @@ -3,10 +3,10 @@ declare(strict_types=1); use Illuminate\Support\Facades\Route; +use Stancl\Tenancy\Database\Concerns\HasDomains; use Stancl\Tenancy\Exceptions\NotASubdomainException; use Stancl\Tenancy\Middleware\InitializeTenancyBySubdomain; - -uses(Stancl\Tenancy\Tests\TestCase::class); +use Stancl\Tenancy\Database\Models; beforeEach(function () { // Global state cleanup after some tests @@ -125,3 +125,8 @@ test('central domain is not a subdomain', function () { ->withoutExceptionHandling() ->get('http://localhost/foo/abc/xyz'); }); + +class SubdomainTenant extends Models\Tenant +{ + use HasDomains; +} diff --git a/tests/TenantAssetTest.php b/tests/TenantAssetTest.php index 662bf799..93a0d3b3 100644 --- a/tests/TenantAssetTest.php +++ b/tests/TenantAssetTest.php @@ -13,8 +13,6 @@ use Stancl\Tenancy\Middleware\InitializeTenancyByDomain; use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - beforeEach(function () { config(['tenancy.bootstrappers' => [ FilesystemTenancyBootstrapper::class, @@ -96,11 +94,8 @@ test('asset helper tenancy can be disabled', function () { expect(asset('foo'))->toBe($original); }); -// Helpers function getEnvironmentSetUp($app) { - parent::getEnvironmentSetUp($app); - $app->booted(function () { if (file_exists(base_path('routes/tenant.php'))) { Route::middleware(['web']) diff --git a/tests/TenantAwareCommandTest.php b/tests/TenantAwareCommandTest.php index 06d31616..1332ccfd 100644 --- a/tests/TenantAwareCommandTest.php +++ b/tests/TenantAwareCommandTest.php @@ -6,8 +6,6 @@ use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\DB; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - test('commands run globally are tenant aware and return valid exit code', function () { $tenant1 = Tenant::create(); $tenant2 = Tenant::create(); diff --git a/tests/TenantDatabaseManagerTest.php b/tests/TenantDatabaseManagerTest.php index b2997661..5a470972 100644 --- a/tests/TenantDatabaseManagerTest.php +++ b/tests/TenantDatabaseManagerTest.php @@ -24,8 +24,6 @@ use Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLSchemaManager; use Stancl\Tenancy\TenantDatabaseManagers\SQLiteDatabaseManager; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - test('databases can be created and deleted', function ($driver, $databaseManager) { Event::listen(TenantCreated::class, JobPipeline::make([CreateDatabase::class])->send(function (TenantCreated $event) { return $event->tenant; @@ -240,7 +238,6 @@ dataset('database_manager_provider', [ ['sqlsrv', MicrosoftSQLDatabaseManager::class] ]); -// Helpers function createUsersTable() { Schema::create('users', function (Blueprint $table) { diff --git a/tests/TenantModelTest.php b/tests/TenantModelTest.php index fb8cfb0e..b8edf766 100644 --- a/tests/TenantModelTest.php +++ b/tests/TenantModelTest.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Schema; @@ -18,8 +19,6 @@ use Stancl\Tenancy\Listeners\BootstrapTenancy; use Stancl\Tenancy\Tests\Etc\Tenant; use Stancl\Tenancy\UUIDGenerator; -uses(Stancl\Tenancy\Tests\TestCase::class); - test('created event is dispatched', function () { Event::fake([TenantCreated::class]); @@ -142,28 +141,38 @@ test('a command can be run on a collection of tenants', function () { expect(Tenant::find('t2')->foo)->toBe('xyz'); }); -// Helpers -function getTenantKeyName(): string +class MyTenant extends Tenant { - return 'id'; + protected $table = 'tenants'; } -function getTenantKey() +class AnotherTenant extends Model implements Contracts\Tenant { - return test()->getAttribute('id'); -} + protected $guarded = []; + protected $table = 'tenants'; -function run(callable $callback) -{ - $callback(); -} + public function getTenantKeyName(): string + { + return 'id'; + } -function getInternal(string $key) -{ - return test()->$key; -} + public function getTenantKey() + { + return $this->getAttribute('id'); + } -function setInternal(string $key, $value) -{ - test()->$key = $value; + public function run(callable $callback) + { + $callback(); + } + + public function getInternal(string $key) + { + return $this->$key; + } + + public function setInternal(string $key, $value) + { + $this->$key = $value; + } } diff --git a/tests/TenantUserImpersonationTest.php b/tests/TenantUserImpersonationTest.php index 2c6808bb..8c5716a0 100644 --- a/tests/TenantUserImpersonationTest.php +++ b/tests/TenantUserImpersonationTest.php @@ -22,8 +22,7 @@ use Stancl\Tenancy\Listeners\RevertToCentralContext; use Stancl\Tenancy\Middleware\InitializeTenancyByDomain; use Stancl\Tenancy\Middleware\InitializeTenancyByPath; use Stancl\Tenancy\Tests\Etc\Tenant; - -uses(Stancl\Tenancy\Tests\TestCase::class); +use Illuminate\Foundation\Auth\User as Authenticable; beforeEach(function () { $this->artisan('migrate', [ @@ -224,7 +223,6 @@ test('impersonation works with multiple models and guards', function () { }); }); -// Helpers function migrateTenants() { test()->artisan('tenants:migrate')->assertExitCode(0); @@ -253,3 +251,15 @@ function getRoutes($loginRoute = true, $authGuard = 'web'): Closure }); }; } + +class ImpersonationUser extends Authenticable +{ + protected $guarded = []; + protected $table = 'users'; +} + +class AnotherImpersonationUser extends Authenticable +{ + protected $guarded = []; + protected $table = 'users'; +} diff --git a/tests/UniversalRouteTest.php b/tests/UniversalRouteTest.php index 4460f0d9..04d053cf 100644 --- a/tests/UniversalRouteTest.php +++ b/tests/UniversalRouteTest.php @@ -7,8 +7,6 @@ use Stancl\Tenancy\Features\UniversalRoutes; use Stancl\Tenancy\Middleware\InitializeTenancyByDomain; use Stancl\Tenancy\Tests\Etc\Tenant; -uses(Stancl\Tenancy\Tests\TestCase::class); - afterEach(function () { InitializeTenancyByDomain::$onFail = null; }); @@ -44,7 +42,30 @@ test('making one route universal doesnt make all routes universal', function () return tenant('id'); })->middleware(InitializeTenancyByDomain::class); - $this->a_route_can_work_in_both_central_and_tenant_context(); + Route::middlewareGroup('universal', []); + config(['tenancy.features' => [UniversalRoutes::class]]); + + Route::get('/foo', function () { + return tenancy()->initialized + ? 'Tenancy is initialized.' + : 'Tenancy is not initialized.'; + })->middleware(['universal', InitializeTenancyByDomain::class]); + + $this->get('http://localhost/foo') + ->assertSuccessful() + ->assertSee('Tenancy is not initialized.'); + + $tenant = Tenant::create([ + 'id' => 'acme', + ]); + $tenant->domains()->create([ + 'domain' => 'acme.localhost', + ]); + + $this->get('http://acme.localhost/foo') + ->assertSuccessful() + ->assertSee('Tenancy is initialized.'); + tenancy()->end(); $this->get('http://localhost/bar')