1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2026-02-06 08:24:03 +00:00

Merge branch 'master' of https://github.com/archtechx/tenancy into add-skip-failing-options-to-migrate

This commit is contained in:
lukinovec 2022-10-05 13:55:07 +02:00
commit b76ed4ad08
94 changed files with 752 additions and 567 deletions

View file

@ -107,12 +107,12 @@ function contextIsSwitchedWhenTenancyInitialized()
class MyBootstrapper implements TenancyBootstrapper
{
public function bootstrap(\Stancl\Tenancy\Contracts\Tenant $tenant)
public function bootstrap(\Stancl\Tenancy\Contracts\Tenant $tenant): void
{
app()->instance('tenancy_initialized_for_tenant', $tenant->getTenantKey());
}
public function revert()
public function revert(): void
{
app()->instance('tenancy_ended', true);
}

View file

@ -30,13 +30,13 @@ test('batch repository is set to tenant connection and reverted', function () {
tenancy()->initialize($tenant);
expect(getBatchRepositoryConnectionName())->toBe('tenant');
tenancy()->initialize($tenant2);
expect(getBatchRepositoryConnectionName())->toBe('tenant');
tenancy()->end();
expect(getBatchRepositoryConnectionName())->toBe('central');
})->skip(fn() => version_compare(app()->version(), '8.0', '<'), 'Job batches are only supported in Laravel 8+');
});
function getBatchRepositoryConnectionName()
{

View file

@ -332,10 +332,6 @@ function getDiskPrefix(string $disk): string
$disk = Storage::disk($disk);
$adapter = $disk->getAdapter();
if (! Str::startsWith(app()->version(), '9.')) {
return $adapter->getPathPrefix();
}
$prefixer = (new ReflectionObject($adapter))->getProperty('prefixer');
$prefixer->setAccessible(true);

View file

@ -6,9 +6,7 @@ use Illuminate\Support\Facades\DB;
use Stancl\Tenancy\Resolvers\DomainTenantResolver;
use Stancl\Tenancy\Tests\Etc\Tenant;
afterEach(function () {
DomainTenantResolver::$shouldCache = false;
});
// todo@v4 test this with other resolvers as well?
test('tenants can be resolved using the cached resolver', function () {
$tenant = Tenant::create();
@ -27,14 +25,14 @@ test('the underlying resolver is not touched when using the cached resolver', fu
DB::enableQueryLog();
DomainTenantResolver::$shouldCache = false;
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => false]);
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
DB::flushQueryLog();
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
pest()->assertNotEmpty(DB::getQueryLog()); // not empty
DomainTenantResolver::$shouldCache = true;
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => true]);
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
DB::flushQueryLog();
@ -50,7 +48,7 @@ test('cache is invalidated when the tenant is updated', function () {
DB::enableQueryLog();
DomainTenantResolver::$shouldCache = true;
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => true]);
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
DB::flushQueryLog();
@ -74,7 +72,7 @@ test('cache is invalidated when a tenants domain is changed', function () {
DB::enableQueryLog();
DomainTenantResolver::$shouldCache = true;
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => true]);
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
DB::flushQueryLog();

View file

@ -9,7 +9,6 @@ use Stancl\Tenancy\Tests\Etc\Tenant;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Artisan;
use PHPUnit\Framework\ExceptionWrapper;
use Stancl\Tenancy\Events\TenancyEnded;
use Stancl\Tenancy\Jobs\CreateDatabase;
use Illuminate\Database\DatabaseManager;
@ -217,8 +216,9 @@ test('run command with array of tenants works', function () {
Artisan::call('tenants:migrate-fresh');
pest()->artisan("tenants:run --tenants=$tenantId1 --tenants=$tenantId2 'foo foo --b=bar --c=xyz'")
->expectsOutput('Tenant: ' . $tenantId1)
->expectsOutput('Tenant: ' . $tenantId2);
->expectsOutputToContain('Tenant: ' . $tenantId1)
->expectsOutputToContain('Tenant: ' . $tenantId2)
->assertExitCode(0);
});
test('link command works', function() {

View file

@ -81,7 +81,7 @@ test('tenant can be identified by domain', function () {
test('onfail logic can be customized', function () {
InitializeTenancyByDomain::$onFail = function () {
return 'foo';
return response('foo');
};
pest()

View file

@ -7,9 +7,13 @@ namespace Stancl\Tenancy\Tests\Etc;
use Stancl\Tenancy\Database\Contracts\TenantWithDatabase;
use Stancl\Tenancy\Database\Concerns\HasDatabase;
use Stancl\Tenancy\Database\Concerns\HasDomains;
use Stancl\Tenancy\Database\Concerns\MaintenanceMode;
use Stancl\Tenancy\Database\Models;
/**
* @method static static create(array $attributes = [])
*/
class Tenant extends Models\Tenant implements TenantWithDatabase
{
use HasDatabase, HasDomains;
use HasDatabase, HasDomains, MaintenanceMode;
}

View file

@ -50,3 +50,17 @@ test('global cache manager stores data in global cache', function () {
expect(cache('def'))->toBe('ghi');
});
test('the global_cache helper supports the same syntax as the cache helper', function () {
$tenant = Tenant::create();
$tenant->enter();
expect(cache('foo'))->toBe(null); // tenant cache is empty
global_cache(['foo' => 'bar']);
expect(global_cache('foo'))->toBe('bar');
global_cache()->set('foo', 'baz');
expect(global_cache()->get('foo'))->toBe('baz');
expect(cache('foo'))->toBe(null); // tenant cache is not affected
});

View file

@ -2,14 +2,14 @@
declare(strict_types=1);
use Illuminate\Support\Facades\Artisan;
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;
test('tenant can be in maintenance mode', function () {
test('tenants can be in maintenance mode', function () {
Route::get('/foo', function () {
return 'bar';
})->middleware([InitializeTenancyByDomain::class, CheckTenantForMaintenanceMode::class]);
@ -19,16 +19,40 @@ test('tenant can be in maintenance mode', function () {
'domain' => 'acme.localhost',
]);
pest()->get('http://acme.localhost/foo')
->assertSuccessful();
tenancy()->end(); // flush stored tenant instance
pest()->get('http://acme.localhost/foo')->assertStatus(200);
$tenant->putDownForMaintenance();
pest()->expectException(HttpException::class);
pest()->withoutExceptionHandling()
->get('http://acme.localhost/foo');
tenancy()->end(); // End tenancy before making a request
pest()->get('http://acme.localhost/foo')->assertStatus(503);
$tenant->bringUpFromMaintenance();
tenancy()->end(); // End tenancy before making a request
pest()->get('http://acme.localhost/foo')->assertStatus(200);
});
test('tenants can be put into maintenance mode using artisan commands', function() {
Route::get('/foo', function () {
return 'bar';
})->middleware([InitializeTenancyByDomain::class, CheckTenantForMaintenanceMode::class]);
$tenant = MaintenanceTenant::create();
$tenant->domains()->create([
'domain' => 'acme.localhost',
]);
pest()->get('http://acme.localhost/foo')->assertStatus(200);
Artisan::call('tenants:down');
tenancy()->end(); // End tenancy before making a request
pest()->get('http://acme.localhost/foo')->assertStatus(503);
Artisan::call('tenants:up');
tenancy()->end(); // End tenancy before making a request
pest()->get('http://acme.localhost/foo')->assertStatus(200);
});
class MaintenanceTenant extends Tenant

View file

@ -10,8 +10,6 @@ use Stancl\Tenancy\Resolvers\PathTenantResolver;
use Stancl\Tenancy\Tests\Etc\Tenant;
beforeEach(function () {
PathTenantResolver::$tenantParameterName = 'tenant';
Route::group([
'prefix' => '/{tenant}',
'middleware' => InitializeTenancyByPath::class,
@ -26,11 +24,6 @@ beforeEach(function () {
});
});
afterEach(function () {
// Global state cleanup
PathTenantResolver::$tenantParameterName = 'tenant';
});
test('tenant can be identified by path', function () {
Tenant::create([
'id' => 'acme',
@ -71,7 +64,7 @@ test('exception is thrown when tenant cannot be identified by path', function ()
test('onfail logic can be customized', function () {
InitializeTenancyByPath::$onFail = function () {
return 'foo';
return response('foo');
};
pest()
@ -101,7 +94,7 @@ test('an exception is thrown when the routes first parameter is not tenant', fun
});
test('tenant parameter name can be customized', function () {
PathTenantResolver::$tenantParameterName = 'team';
config(['tenancy.identification.resolvers.' . PathTenantResolver::class . '.tenant_parameter_name' => 'team']);
Route::group([
'prefix' => '/{team}',

View file

@ -37,7 +37,6 @@ test('header identification works', function () {
});
test('query parameter identification works', function () {
InitializeTenancyByRequestData::$header = null;
InitializeTenancyByRequestData::$queryParameter = 'tenant';
$tenant = Tenant::create();

View file

@ -13,8 +13,6 @@ use Stancl\Tenancy\Database\Concerns\HasScopedValidationRules;
use Stancl\Tenancy\Tests\Etc\Tenant as TestTenant;
beforeEach(function () {
BelongsToTenant::$tenantIdColumn = 'tenant_id';
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('text');
@ -144,7 +142,7 @@ test('tenant id is not auto added when creating primary resources in central con
});
test('tenant id column name can be customized', function () {
BelongsToTenant::$tenantIdColumn = 'team_id';
config(['tenancy.single_db.tenant_id_column' => 'team_id']);
Schema::drop('comments');
Schema::drop('posts');

View file

@ -44,7 +44,7 @@ test('tenant can be identified by subdomain', function () {
test('onfail logic can be customized', function () {
InitializeTenancyBySubdomain::$onFail = function () {
return 'foo';
return response('foo');
};
pest()

View file

@ -6,10 +6,8 @@ use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Storage;
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
use Stancl\Tenancy\Controllers\TenantAssetsController;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData;
use Stancl\Tenancy\Tests\Etc\Tenant;
@ -21,13 +19,8 @@ beforeEach(function () {
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
});
afterEach(function () {
// Cleanup
TenantAssetsController::$tenancyMiddleware = InitializeTenancyByDomain::class;
});
test('asset can be accessed using the url returned by the tenant asset helper', function () {
TenantAssetsController::$tenancyMiddleware = InitializeTenancyByRequestData::class;
config(['tenancy.identification.default_middleware' => InitializeTenancyByRequestData::class]);
$tenant = Tenant::create();
tenancy()->initialize($tenant);
@ -95,7 +88,7 @@ test('asset helper tenancy can be disabled', function () {
});
test('test asset controller returns a 404 when no path is provided', function () {
TenantAssetsController::$tenancyMiddleware = InitializeTenancyByRequestData::class;
config(['tenancy.identification.default_middleware' => InitializeTenancyByRequestData::class]);
$tenant = Tenant::create();

View file

@ -154,9 +154,7 @@ test('schema manager uses schema to separate tenant dbs', function () {
]);
tenancy()->initialize($tenant);
$schemaConfig = version_compare(app()->version(), '9.0', '>=') ?
config('database.connections.' . config('database.default') . '.search_path') :
config('database.connections.' . config('database.default') . '.schema');
$schemaConfig = config('database.connections.' . config('database.default') . '.search_path');
expect($schemaConfig)->toBe($tenant->database()->getName());
expect(config(['database.connections.pgsql.database']))->toBe($originalDatabaseName);

View file

@ -103,7 +103,7 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
'--realpath' => true,
'--force' => true,
],
'tenancy.bootstrappers.redis' => RedisTenancyBootstrapper::class, // todo0 change this to []? two tests in TenantDatabaseManagerTest are failing with that
'tenancy.bootstrappers.redis' => RedisTenancyBootstrapper::class, // todo1 change this to []? two tests in TenantDatabaseManagerTest are failing with that
'queue.connections.central' => [
'driver' => 'sync',
'central' => true,