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

Merge branch 'master' into august

This commit is contained in:
Samuel Štancl 2025-08-25 17:44:11 +02:00
commit 1f0c668578
6 changed files with 128 additions and 47 deletions

View file

@ -27,6 +27,7 @@ use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper;
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
use Stancl\Tenancy\Database\Exceptions\TenantDatabaseDoesNotExistException;
use function Stancl\Tenancy\Tests\pest;
use Stancl\Tenancy\Events\MigratingDatabase;
beforeEach(function () {
if (file_exists($schemaPath = 'tests/Etc/tenant-schema-test.dump')) {
@ -95,6 +96,60 @@ test('migrate command works with tenants option', function () {
expect(Schema::hasTable('users'))->toBeTrue();
});
test('migrate command uses the passed database option as the template tenant connection', function () {
$originalTemplateConnection = config('tenancy.database.template_tenant_connection');
// Add a custom connection that will be used as the template for the tenant connection
// Identical to the default (mysql), just with different charset and collation
config(['database.connections.custom_connection' => [
"driver" => "mysql",
"url" => "",
"host" => "mysql",
"port" => "3306",
"database" => "main",
"username" => "root",
"password" => "password",
"unix_socket" => "",
"charset" => "latin1", // Different from the default (utf8mb4)
"collation" => "latin1_swedish_ci", // Different from the default (utf8mb4_unicode_ci)
"prefix" => "",
"prefix_indexes" => true,
"strict" => true,
"engine" => null,
"options" => []
]]);
$templateConnectionDuringMigration = null;
$tenantConnectionDuringMigration = null;
Event::listen(MigratingDatabase::class, function() use (&$templateConnectionDuringMigration, &$tenantConnectionDuringMigration) {
$templateConnectionDuringMigration = config('tenancy.database.template_tenant_connection');
$tenantConnectionDuringMigration = DB::connection('tenant')->getConfig();
});
// The original tenant template connection config remains default
expect(config('tenancy.database.template_tenant_connection'))->toBe($originalTemplateConnection);
Tenant::create();
// The original template connection is used when the --database option is not passed
pest()->artisan('tenants:migrate');
expect($templateConnectionDuringMigration)->toBe($originalTemplateConnection);
Tenant::create();
// The migrate command temporarily uses the connection passed in the --database option
pest()->artisan('tenants:migrate', ['--database' => 'custom_connection']);
expect($templateConnectionDuringMigration)->toBe('custom_connection');
// The tenant connection during migration actually used custom_connection's config
expect($tenantConnectionDuringMigration['charset'])->toBe('latin1');
expect($tenantConnectionDuringMigration['collation'])->toBe('latin1_swedish_ci');
// The tenant template connection config is restored to the original after migrating
expect(config('tenancy.database.template_tenant_connection'))->toBe($originalTemplateConnection);
});
test('migrate command only throws exceptions if skip-failing is not passed', function() {
Tenant::create();
@ -311,6 +366,21 @@ test('migrate fresh command works', function () {
expect(DB::table('users')->exists())->toBeFalse();
});
test('migrate fresh command respects force option in production', function () {
// Set environment to production
app()->detectEnvironment(fn() => 'production');
Tenant::create();
// Without --force in production, command should prompt for confirmation
pest()->artisan('tenants:migrate-fresh')
->expectsConfirmation('Are you sure you want to run this command?');
// With --force, command should succeed without prompting
pest()->artisan('tenants:migrate-fresh', ['--force' => true])
->assertSuccessful();
});
test('run command with array of tenants works', function () {
$tenantId1 = Tenant::create()->getTenantKey();
$tenantId2 = Tenant::create()->getTenantKey();

View file

@ -3,27 +3,41 @@
declare(strict_types=1);
use Illuminate\Foundation\Vite;
use Stancl\Tenancy\Tests\Etc\Tenant;
use Stancl\Tenancy\Overrides\Vite as StanclVite;
use Illuminate\Support\Facades\File;
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
use Stancl\Tenancy\Features\ViteBundler;
use Stancl\Tenancy\Tests\Etc\Tenant;
test('vite helper uses our custom class', function() {
$vite = app(Vite::class);
expect($vite)->toBeInstanceOf(Vite::class);
expect($vite)->not()->toBeInstanceOf(StanclVite::class);
use function Stancl\Tenancy\Tests\withBootstrapping;
beforeEach(function () {
config([
'tenancy.features' => [ViteBundler::class],
'tenancy.filesystem.asset_helper_override' => true,
'tenancy.bootstrappers' => [FilesystemTenancyBootstrapper::class],
]);
$tenant = Tenant::create();
tenancy()->initialize($tenant);
app()->forgetInstance(Vite::class);
$vite = app(Vite::class);
expect($vite)->toBeInstanceOf(StanclVite::class);
File::ensureDirectoryExists(dirname($manifestPath = public_path('build/manifest.json')));
File::put($manifestPath, json_encode([
'foo' => [
'file' => 'assets/foo-AbC123.js',
'src' => 'js/foo.js',
],
]));
});
test('vite bundler ensures vite assets use global_asset when asset_helper_override is enabled', function () {
config(['tenancy.features' => [ViteBundler::class]]);
withBootstrapping();
tenancy()->initialize(Tenant::create());
// Not what we want
expect(asset('foo'))->toBe(route('stancl.tenancy.asset', ['path' => 'foo']));
$viteAssetUrl = app(Vite::class)->asset('foo');
$expectedGlobalUrl = global_asset('build/assets/foo-AbC123.js');
expect($viteAssetUrl)->toBe($expectedGlobalUrl);
expect($viteAssetUrl)->toBe('http://localhost/build/assets/foo-AbC123.js');
});