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 e25e7b7961
Single-domain tenants (#16)
* Add SingleDomainTenant

* Add logic for single domain tenants

* Test that the single domain approach works (wip)

* Fix code style (php-cs-fixer)

* Simplify SubdomainTest tests

* Add single domain tenant conditions to DomainTenantResolver

* Test single domain tenants in resolver test

* Fix test name typo

* Improve runUsingBothDomainApproaches()

* Delete extra tenancy()->end()

* Test early identification with both domain approaches

* Test that things work with both domain approaches in the rest of the tests

* Fix falsely passing test

* Fix PHPStan errors

* Change SingleDomainTenant to a contract, add SingleDomainTenant test model

* Fix TenantList domainsCLI()

* Improve setCurrentDomain() check

* Fix code style (php-cs-fixer)

* Add annotation

* Revert getCustomColumns() change

* Add comments

* Use the domain returned by the closure in runUsingBoth..()

* Delete `migrate` from test

* Improve test names

* Use variable instead of repeating the same string multiple times

* Update comment

* Add comment

* Clean up PreventAccess test

* Don't assign domain to a single-use variable

* Update comments

* Uncomment datasets

* Add todo

* Fix user impersonation test

* Don't specify tenant key when creating tenant in runUsingBoth..()

* Improve universal route test

* Improve `runUsingBothDomainApproaches()`

* Add tests specific to single domain tenants

* Get rid of the runUsingBothDomainApproaches method

* Add test file specific for the single domain tenant feature

* Rename test

* Make getCustomColumns() function static

* Positiopn datasets differently

* Fix early id test

* Add prevent MW to route MW in test

* Fix single domain tenant tests

* Delete SingleDomainTenantTest (CI testing)

* Add the test file back

* TUrn APP_DEBUG on temporarily

* Turn debug off

* Try creating tenant with non-unique domain (CI testing)

* dd duplicate tenant records

* Revert testing change

* Make SingleDomainTenant not extend base tenant (VirtualColumn issues)

* Fix early id test

* add todo

* Use dev-master stancl/virtualcolumn

* Make SingleDomainTenant extend the tenant base model

* remove todo

* Clean up EarlyIdentificationTest changes

* Finish test file cleanup

* Fix test

* improve test

---------

Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
2023-11-08 11:38:26 +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([
[
'domain' => 'acme.localhost',
'identification middleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyByDomain::class],
],
[
'subdomain' => 'acme',
'identification middleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyBySubdomain::class],
],
]);