1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-12 14:14:04 +00:00

Resolve test to-dos (#45)

* Only retrieve domains if the relationship and the domains table exist (DomianTenantResolver)

* Resolve todo, add other todos

* Use constructor promotion in DeleteDomains

* Fix imports + domain deletion test

* Confirm that turning on resolver caching doesn't break the tests

* Fix Tenant model imports

* Fix code style (php-cs-fixer)

* remove runtime schema check

* temp: enable resolver cache

* make 'autoincrement ids are supported' pass

* disable resolver cache

---------

Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
Co-authored-by: Samuel Štancl <samuel@archte.ch>
This commit is contained in:
lukinovec 2024-04-18 00:22:03 +02:00 committed by GitHub
parent 3e441e075f
commit 6e67ddf7a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 85 additions and 80 deletions

View file

@ -100,7 +100,7 @@ return [
*/
'resolvers' => [
Resolvers\DomainTenantResolver::class => [
'cache' => false, // todo@tests find why some tests fail when these are set to true
'cache' => false,
'cache_ttl' => 3600, // seconds
'cache_store' => null, // null = default
],

View file

@ -65,6 +65,7 @@
"scripts": {
"docker-up": "docker-compose up -d",
"docker-down": "docker-compose down",
"docker-restart": "docker-compose down && docker-compose up -d",
"docker-rebuild": "PHP_VERSION=8.3 docker-compose up -d --no-deps --build",
"docker-m1": "ln -s docker-compose-m1.override.yml docker-compose.override.yml",
"coverage": "open coverage/phpunit/html/index.html",

View file

@ -15,12 +15,9 @@ class DeleteDomains
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected TenantWithDatabase&Model $tenant;
public function __construct(TenantWithDatabase&Model $tenant)
{
$this->tenant = $tenant;
}
public function __construct(
protected TenantWithDatabase&Model $tenant,
) {}
public function handle(): void
{

View file

@ -4,13 +4,15 @@ declare(strict_types=1);
namespace Stancl\Tenancy\Resolvers;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Stancl\Tenancy\Contracts\Domain;
use Stancl\Tenancy\Contracts\SingleDomainTenant;
use Stancl\Tenancy\Contracts\Tenant;
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedOnDomainException;
use Stancl\Tenancy\Tenancy;
use Stancl\Tenancy\Contracts\Domain;
use Stancl\Tenancy\Contracts\Tenant;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Stancl\Tenancy\Contracts\SingleDomainTenant;
use Illuminate\Database\Eloquent\Relations\Relation;
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedOnDomainException;
class DomainTenantResolver extends Contracts\CachedTenantResolver
{
@ -69,12 +71,14 @@ class DomainTenantResolver extends Contracts\CachedTenantResolver
public function getPossibleCacheKeys(Tenant&Model $tenant): array
{
$domains = [];
if ($tenant instanceof SingleDomainTenant) {
$domains = array_filter([
$tenant->getOriginal('domain'), // Previous domain
$tenant->domain, // Current domain
]);
} else {
} elseif (method_exists($tenant, 'domains') && $tenant->domains() instanceof Relation) {
/** @var Tenant&Model $tenant */
$tenant->unsetRelation('domains');

View file

@ -1,19 +1,20 @@
<?php
use Illuminate\Broadcasting\BroadcastManager;
use Illuminate\Database\Schema\Blueprint;
use Stancl\JobPipeline\JobPipeline;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Schema;
use Stancl\JobPipeline\JobPipeline;
use Stancl\Tenancy\Bootstrappers\BroadcastChannelPrefixBootstrapper;
use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper;
use Stancl\Tenancy\Events\TenancyEnded;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Events\TenantCreated;
use Stancl\Tenancy\Jobs\CreateDatabase;
use Stancl\Tenancy\Events\TenantCreated;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Broadcasting\BroadcastManager;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Tests\Etc\TestingBroadcaster;
use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper;
use Stancl\Tenancy\Bootstrappers\BroadcastChannelPrefixBootstrapper;
beforeEach(function () {
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
@ -139,4 +140,3 @@ test('BroadcastChannelPrefixBootstrapper prefixes the channels events are broadc
expect(app(BroadcastManager::class)->driver())->toBe($broadcaster);
expect(invade(app(BroadcastManager::class)->driver())->formatChannels($channelNames))->toEqual($channelNames);
});

View file

@ -1,14 +1,15 @@
<?php
use Illuminate\Broadcasting\BroadcastManager;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Illuminate\Support\Facades\Event;
use Stancl\Tenancy\Bootstrappers\BroadcastingConfigBootstrapper;
use Stancl\Tenancy\Events\TenancyEnded;
use Illuminate\Broadcasting\BroadcastManager;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Tests\Etc\TestingBroadcaster;
use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Overrides\TenancyBroadcastManager;
use Stancl\Tenancy\Tests\Etc\TestingBroadcaster;
use Stancl\Tenancy\Bootstrappers\BroadcastingConfigBootstrapper;
beforeEach(function () {
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
@ -102,4 +103,3 @@ test('BroadcastingConfigBootstrapper makes the app use broadcasters with the cor
expect(invade(app(BroadcastManager::class)->driver())->message)->toBe($defaultMessage);
});

View file

@ -3,6 +3,7 @@
declare(strict_types=1);
use Illuminate\Cache\CacheManager;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Illuminate\Support\Facades\Event;
use Stancl\Tenancy\Events\TenancyEnded;
use Stancl\Tenancy\Tests\Etc\CacheService;

View file

@ -1,20 +1,21 @@
<?php
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Stancl\JobPipeline\JobPipeline;
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
use Stancl\Tenancy\Events\DeletingTenant;
use Illuminate\Support\Facades\File;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Storage;
use Stancl\Tenancy\Events\TenancyEnded;
use Stancl\Tenancy\Events\TenantCreated;
use Stancl\Tenancy\Events\TenantDeleted;
use Stancl\Tenancy\Events\DeletingTenant;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Jobs\CreateStorageSymlinks;
use Stancl\Tenancy\Jobs\RemoveStorageSymlinks;
use Stancl\Tenancy\Listeners\DeleteTenantStorage;
use Stancl\Tenancy\Events\TenancyEnded;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Listeners\DeleteTenantStorage;
use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
beforeEach(function () {
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);

View file

@ -1,13 +1,14 @@
<?php
use Stancl\Tenancy\Enums\Context;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Route;
use Stancl\Tenancy\Bootstrappers\Integrations\FortifyRouteBootstrapper;
use Stancl\Tenancy\Enums\Context;
use Stancl\Tenancy\Events\TenancyEnded;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Bootstrappers\Integrations\FortifyRouteBootstrapper;
beforeEach(function () {
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);

View file

@ -1,14 +1,15 @@
<?php
use Illuminate\Support\Facades\URL;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\URL;
use Stancl\Tenancy\Bootstrappers\RootUrlBootstrapper;
use Stancl\Tenancy\Middleware\InitializeTenancyBySubdomain;
use Stancl\Tenancy\Events\TenancyEnded;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Bootstrappers\RootUrlBootstrapper;
use Stancl\Tenancy\Middleware\InitializeTenancyBySubdomain;
beforeEach(function () {
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
@ -64,4 +65,3 @@ test('root url bootstrapper overrides the root url when tenancy gets initialized
expect(URL::to('/'))->toBe($baseUrl);
expect(config('app.url'))->toBe($baseUrl);
});

View file

@ -1,18 +1,19 @@
<?php
use Illuminate\Routing\Exceptions\UrlGenerationException;
use Illuminate\Routing\UrlGenerator;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Route;
use Stancl\Tenancy\Bootstrappers\UrlGeneratorBootstrapper;
use Stancl\Tenancy\Middleware\InitializeTenancyByPath;
use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData;
use Stancl\Tenancy\Overrides\TenancyUrlGenerator;
use Stancl\Tenancy\Resolvers\PathTenantResolver;
use Stancl\Tenancy\Events\TenancyEnded;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Resolvers\PathTenantResolver;
use Stancl\Tenancy\Overrides\TenancyUrlGenerator;
use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Middleware\InitializeTenancyByPath;
use Illuminate\Routing\Exceptions\UrlGenerationException;
use Stancl\Tenancy\Bootstrappers\UrlGeneratorBootstrapper;
use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData;
beforeEach(function () {
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);

View file

@ -2,7 +2,8 @@
declare(strict_types=1);
use Illuminate\Broadcasting\Broadcasters\NullBroadcaster;
use Illuminate\Support\Collection;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Schema;
use Stancl\Tenancy\Events\TenancyEnded;
@ -14,10 +15,10 @@ use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Tests\Etc\TestingBroadcaster;
use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Overrides\TenancyBroadcastManager;
use Illuminate\Broadcasting\Broadcasters\NullBroadcaster;
use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper;
use Stancl\Tenancy\Bootstrappers\BroadcastingConfigBootstrapper;
use Illuminate\Contracts\Broadcasting\Broadcaster as BroadcasterContract;
use Illuminate\Support\Collection;
beforeEach(function () {
withTenantDatabases();

View file

@ -2,6 +2,7 @@
use Illuminate\Routing\Route;
use Stancl\Tenancy\Enums\RouteMode;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Illuminate\Contracts\Http\Kernel;
use Stancl\Tenancy\Actions\CloneRoutesAsTenant;
use Stancl\Tenancy\Resolvers\PathTenantResolver;
@ -9,7 +10,6 @@ use Illuminate\Support\Facades\Route as RouteFacade;
use Stancl\Tenancy\Tests\Etc\HasMiddlewareController;
use Stancl\Tenancy\Middleware\InitializeTenancyByPath;
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
use Stancl\Tenancy\PathIdentificationManager;
test('a route can be universal using path identification', function (array $routeMiddleware, array $globalMiddleware) {
foreach ($globalMiddleware as $middleware) {

View file

@ -2,15 +2,15 @@
declare(strict_types=1);
use Stancl\Tenancy\Database\Concerns\HasDomains;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Stancl\Tenancy\Jobs\DeleteDomains;
beforeEach(function () {
config(['tenancy.models.tenant' => DatabaseAndDomainTenant::class]);
config(['tenancy.models.tenant' => Tenant::class]);
});
test('job deletes domains successfully', function () {
$tenant = DatabaseAndDomainTenant::create();
$tenant = Tenant::create();
$tenant->domains()->create([
'domain' => 'foo.localhost',
@ -21,12 +21,7 @@ test('job deletes domains successfully', function () {
expect($tenant->domains()->count())->toBe(2);
(new DeleteDomains($tenant))->handle();
(new DeleteDomains($tenant->refresh()))->handle();
expect($tenant->refresh()->domains()->count())->toBe(0);
});
class DatabaseAndDomainTenant extends \Stancl\Tenancy\Tests\Etc\Tenant
{
use HasDomains;
}

View file

@ -3,6 +3,7 @@
declare(strict_types=1);
use Illuminate\Mail\MailManager;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Illuminate\Support\Facades\Event;
use Stancl\Tenancy\Events\TenancyEnded;
use Stancl\Tenancy\Events\TenancyInitialized;

View file

@ -3,6 +3,7 @@
declare(strict_types=1);
use Stancl\Tenancy\Enums\RouteMode;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Support\Facades\Route;
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;

View file

@ -2,15 +2,15 @@
declare(strict_types=1);
use Illuminate\Support\Facades\Schema;
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\Models\Tenant;
use Stancl\Tenancy\Database\Concerns\BelongsToTenant;
use Stancl\Tenancy\Database\Concerns\BelongsToPrimaryModel;
use Stancl\Tenancy\Database\Concerns\HasScopedValidationRules;
use Stancl\Tenancy\Tests\Etc\Tenant as TestTenant;
beforeEach(function () {
Schema::create('posts', function (Blueprint $table) {
@ -31,12 +31,12 @@ beforeEach(function () {
$table->foreign('post_id')->references('id')->on('posts')->onUpdate('cascade')->onDelete('cascade');
});
config(['tenancy.models.tenant' => Tenant::class]);
config(['tenancy.models.tenant' => SingleDatabaseTenant::class]);
});
test('primary models are scoped to the current tenant', function () {
// acme context
tenancy()->initialize($acme = Tenant::create([
tenancy()->initialize($acme = SingleDatabaseTenant::create([
'id' => 'acme',
]));
@ -52,7 +52,7 @@ test('primary models are scoped to the current tenant', function () {
// ======================================
// foobar context
tenancy()->initialize(Tenant::create([
tenancy()->initialize(SingleDatabaseTenant::create([
'id' => 'foobar',
]));
@ -85,7 +85,7 @@ test('primary models are scoped to the current tenant', function () {
});
test('secondary models ARE scoped to the current tenant when accessed directly and parent relationship trait is used', function () {
$acme = Tenant::create([
$acme = SingleDatabaseTenant::create([
'id' => 'acme',
]);
@ -97,7 +97,7 @@ test('secondary models ARE scoped to the current tenant when accessed directly a
expect(ScopedComment::count())->toBe(1);
});
$foobar = Tenant::create([
$foobar = SingleDatabaseTenant::create([
'id' => 'foobar',
]);
@ -119,7 +119,7 @@ test('secondary models ARE scoped to the current tenant when accessed directly a
test('secondary models are scoped correctly', function () {
// Secondary models are scoped to the current tenant when accessed via primary model
// acme context
tenancy()->initialize($acme = Tenant::create([
tenancy()->initialize($acme = SingleDatabaseTenant::create([
'id' => 'acme',
]));
@ -128,7 +128,7 @@ test('secondary models are scoped correctly', function () {
// ================
// foobar context
tenancy()->initialize(Tenant::create([
tenancy()->initialize(SingleDatabaseTenant::create([
'id' => 'foobar',
]));
@ -161,7 +161,7 @@ test('global models are not scoped at all', function () {
GlobalResource::create(['text' => 'First']);
GlobalResource::create(['text' => 'Second']);
$acme = Tenant::create([
$acme = SingleDatabaseTenant::create([
'id' => 'acme',
]);
@ -176,7 +176,7 @@ test('global models are not scoped at all', function () {
});
test('tenant id and relationship is auto added when creating primary resources in tenant context', function () {
tenancy()->initialize($acme = Tenant::create([
tenancy()->initialize($acme = SingleDatabaseTenant::create([
'id' => 'acme',
]));
@ -208,9 +208,11 @@ test('tenant id column name can be customized', function () {
$table->foreign('team_id')->references('id')->on('tenants')->onUpdate('cascade')->onDelete('cascade');
});
tenancy()->initialize($acme = Tenant::create([
$acme = SingleDatabaseTenant::create([
'id' => 'acme',
]));
]);
tenancy()->initialize($acme);
$post = Post::create(['text' => 'Foo']);
@ -218,7 +220,7 @@ test('tenant id column name can be customized', function () {
// ======================================
// foobar context
tenancy()->initialize($foobar = Tenant::create([
tenancy()->initialize($foobar = SingleDatabaseTenant::create([
'id' => 'foobar',
]));
@ -248,7 +250,7 @@ test('the model returned by the tenant helper has unique and exists validation r
$table->unique(['tenant_id', 'slug']);
});
tenancy()->initialize($acme = Tenant::create([
tenancy()->initialize($acme = SingleDatabaseTenant::create([
'id' => 'acme',
]));
@ -278,7 +280,7 @@ test('the model returned by the tenant helper has unique and exists validation r
expect($existsFails)->toBeFalse();
});
class Tenant extends TestTenant
class SingleDatabaseTenant extends Tenant
{
use HasScopedValidationRules;
}

View file

@ -64,8 +64,8 @@ test('autoincrement ids are supported', function () {
unset(app()[UniqueIdentifierGenerator::class]);
$tenant1 = Tenant::create();
$tenant2 = Tenant::create();
$tenant1 = MyTenant::create();
$tenant2 = MyTenant::create();
expect($tenant1->id)->toBe(1);
expect($tenant2->id)->toBe(2);
@ -200,8 +200,7 @@ test('currentOrFail method throws an exception if there is no currently initiali
expect(fn() => Tenant::currentOrFail())->toThrow(TenancyNotInitializedException::class);
});
class MyTenant extends Tenant
class MyTenant extends Stancl\Tenancy\Database\Models\Tenant
{
protected $table = 'tenants';
}