1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-12 22:14:03 +00:00
tenancy/tests/SingleDomainTenantTest.php
lukinovec cb0d7e2902
Improve early identification tests (#66)
* Separate route-level domain identification test from path/request to improve readability WIP

* Get rid of confusing datasets in route-level identifcation tests

* Clean up updated tests

* Simplify early id tests

* Reduce dataset duplication

* Improve test readability, fix false positive,  polish details

* Separate early ID test from defaulting test (WIP)

* Finish improving and correcting the early identification/default route mode tests

* Make flag/default mode usage more clear by improving the docblock in DealsWithRouteContexts

* Fix PHPUnit deprecation warnings

* code review

* code review

---------

Co-authored-by: Samuel Štancl <samuel@archte.ch>
2024-12-20 03:42:23 +01:00

133 lines
5.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
use Stancl\Tenancy\Tests\Etc\SingleDomainTenant;
use Stancl\Tenancy\Resolvers\DomainTenantResolver;
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
use Illuminate\Database\UniqueConstraintViolationException;
use Stancl\Tenancy\Middleware\InitializeTenancyBySubdomain;
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedOnDomainException;
use Stancl\Tenancy\Middleware\PreventAccessFromUnwantedDomains;
beforeEach(function () {
config(['tenancy.models.tenant' => SingleDomainTenant::class]);
pest()->artisan('migrate', [
'--path' => __DIR__ . '/Etc/2023_08_08_000001_add_domain_column.php',
'--realpath' => true,
])->assertExitCode(0);
});
test('tenant can be resolved by its domain using the cached resolver', function () {
$tenant = SingleDomainTenant::create(['domain' => 'acme']);
$tenant2 = SingleDomainTenant::create(['domain' => 'bar.domain.test']);
expect($tenant->is(app(DomainTenantResolver::class)->resolve($tenant->domain)))->toBeTrue();
expect($tenant->is(app(DomainTenantResolver::class)->resolve($tenant2->domain)))->toBeFalse();
expect($tenant2->is(app(DomainTenantResolver::class)->resolve($tenant2->domain)))->toBeTrue();
expect($tenant2->is(app(DomainTenantResolver::class)->resolve($tenant->domain)))->toBeFalse();
});
test('cache is invalidated when single domain tenant is updated', function () {
DB::enableQueryLog();
config([
'tenancy.models.tenant' => SingleDomainTenant::class,
'tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => true
]);
$tenant = SingleDomainTenant::create(['domain' => $subdomain = 'acme']);
expect($tenant->is(app(DomainTenantResolver::class)->resolve($subdomain)))->toBeTrue();
DB::flushQueryLog();
expect($tenant->is(app(DomainTenantResolver::class)->resolve($subdomain)))->toBeTrue();
expect(DB::getQueryLog())->toBeEmpty(); // empty
$tenant->update(['foo' => 'bar']);
DB::flushQueryLog();
expect($tenant->is(app(DomainTenantResolver::class)->resolve($subdomain)))->toBeTrue();
pest()->assertNotEmpty(DB::getQueryLog()); // not empty
});
test('cache is invalidated when a single domain tenants domain is updated', function () {
DB::enableQueryLog();
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => true]);
$tenant = SingleDomainTenant::create(['domain' => 'acme']);
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
DB::flushQueryLog();
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
pest()->assertEmpty(DB::getQueryLog()); // Empty tenant retrieved from cache
$tenant->update(['domain' => 'bar']);
DB::flushQueryLog();
expect(fn () => $tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toThrow(TenantCouldNotBeIdentifiedOnDomainException::class);
pest()->assertNotEmpty(DB::getQueryLog()); // resolving old subdomain (not in cache anymore)
DB::flushQueryLog();
expect($tenant->is(app(DomainTenantResolver::class)->resolve('bar')))->toBeTrue();
pest()->assertNotEmpty(DB::getQueryLog()); // resolving using new subdomain for the first time
DB::flushQueryLog();
expect($tenant->is(app(DomainTenantResolver::class)->resolve('bar')))->toBeTrue();
pest()->assertEmpty(DB::getQueryLog()); // resolving using new subdomain for the second time
$tenant->update(['domain' => 'baz']);
DB::flushQueryLog();
expect(fn () => $tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toThrow(TenantCouldNotBeIdentifiedOnDomainException::class);
pest()->assertNotEmpty(DB::getQueryLog()); // resolving using first old subdomain - no cache + failed
DB::flushQueryLog();
expect(fn () => $tenant->is(app(DomainTenantResolver::class)->resolve('bar')))->toThrow(TenantCouldNotBeIdentifiedOnDomainException::class);
pest()->assertNotEmpty(DB::getQueryLog()); // resolving using second old subdomain - no cache + failed
DB::flushQueryLog();
expect($tenant->is(app(DomainTenantResolver::class)->resolve('baz')))->toBeTrue();
pest()->assertNotEmpty(DB::getQueryLog()); // resolving using current subdomain for the first time
DB::flushQueryLog();
expect($tenant->is(app(DomainTenantResolver::class)->resolve('baz')))->toBeTrue();
pest()->assertEmpty(DB::getQueryLog()); // resolving using current subdomain for the second time
});
test('tenant has to have a unique domain', function() {
SingleDomainTenant::create(['domain' => 'bar']);
expect(fn () => SingleDomainTenant::create(['domain' => 'bar']))->toThrow(UniqueConstraintViolationException::class);
});
test('single domain tenant can be identified by domain or subdomain', function (string $domain, array $identificationMiddleware) {
$tenant = SingleDomainTenant::create(['domain' => $domain]);
Route::get('/foo/{a}/{b}', function ($a, $b) {
return "$a + $b";
})->middleware($identificationMiddleware);
if ($domain === 'acme') {
$domain .= '.localhost';
}
pest()
->get("http://{$domain}/foo/abc/xyz")
->assertSee('abc + xyz');
expect(tenant('id'))->toBe($tenant->id);
})->with([
[
'acme.localhost', // Domain
[PreventAccessFromUnwantedDomains::class, InitializeTenancyByDomain::class], // Identification middleware
],
[
'acme', // Subdomain
[PreventAccessFromUnwantedDomains::class, InitializeTenancyBySubdomain::class], // Identification middleware
],
]);