mirror of
https://github.com/archtechx/tenancy.git
synced 2026-02-05 02:54:03 +00:00
Try simplifying the tests
This commit is contained in:
parent
e199b9d50c
commit
bcf1f641ca
1 changed files with 50 additions and 54 deletions
|
|
@ -47,6 +47,7 @@ use Illuminate\Database\Eloquent\Scope;
|
||||||
use Illuminate\Database\Eloquent\Attributes\ScopedBy;
|
use Illuminate\Database\Eloquent\Attributes\ScopedBy;
|
||||||
use Illuminate\Database\QueryException;
|
use Illuminate\Database\QueryException;
|
||||||
use function Stancl\Tenancy\Tests\pest;
|
use function Stancl\Tenancy\Tests\pest;
|
||||||
|
use Illuminate\Database\UniqueConstraintViolationException;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
config(['tenancy.bootstrappers' => [
|
config(['tenancy.bootstrappers' => [
|
||||||
|
|
@ -117,6 +118,7 @@ test('resources created with the same global id in different tenant dbs will be
|
||||||
|
|
||||||
// Only a single central user is created since the same global_id is used for each tenant user
|
// Only a single central user is created since the same global_id is used for each tenant user
|
||||||
// Therefore all of these tenant users are synced to a single global user
|
// Therefore all of these tenant users are synced to a single global user
|
||||||
|
expect(function () use ($tenants) {
|
||||||
tenancy()->runForMultiple($tenants, function () {
|
tenancy()->runForMultiple($tenants, function () {
|
||||||
// Create a user with the same global_id in each tenant DB
|
// Create a user with the same global_id in each tenant DB
|
||||||
TenantUser::create([
|
TenantUser::create([
|
||||||
|
|
@ -127,9 +129,10 @@ test('resources created with the same global id in different tenant dbs will be
|
||||||
'role' => 'commenter',
|
'role' => 'commenter',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
})->not()
|
||||||
expect(CentralUser::all())->toHaveCount(1);
|
// The central resource is only created once,
|
||||||
expect(CentralUser::first()->global_id)->toBe('acme');
|
// so the unique constraint violation exception isn't thrown
|
||||||
|
->toThrow(UniqueConstraintViolationException::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('SyncedResourceSaved event gets triggered when resource gets created or when its synced attributes get updated', function () {
|
test('SyncedResourceSaved event gets triggered when resource gets created or when its synced attributes get updated', function () {
|
||||||
|
|
@ -1197,70 +1200,63 @@ test('resource creation works correctly when central resource provides defaults
|
||||||
expect($centralUser->foo)->toBe('bar');
|
expect($centralUser->foo)->toBe('bar');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('scopeGetModelQuery allows customizing the query used to find resources during syncing', function (bool $scopeGetModelQuery) {
|
test('resource syncing broken by custom scopes can get fixed by scopeGetModelQuery', function (bool $scopeGetModelQuery) {
|
||||||
[$tenant1, $tenant2] = createTenantsAndRunMigrations();
|
[$tenant1, $tenant2] = createTenantsAndRunMigrations();
|
||||||
migrateUsersTableForTenants();
|
migrateUsersTableForTenants();
|
||||||
addExtraColumns(true);
|
|
||||||
|
|
||||||
TenantUserWithSoftDeletes::$creationAttributes = [
|
|
||||||
'role' => 'role',
|
|
||||||
'foo' => 'foo',
|
|
||||||
];
|
|
||||||
|
|
||||||
if ($scopeGetModelQuery) {
|
if ($scopeGetModelQuery) {
|
||||||
// Configure resource syncing to include soft deleted records
|
// Configure scopeGetModelQuery to remove the custom scope that would break syncing
|
||||||
// when looking up resources (the documented use case for $scopeGetModelQuery)
|
|
||||||
UpdateOrCreateSyncedResource::$scopeGetModelQuery = function (Builder $query) {
|
UpdateOrCreateSyncedResource::$scopeGetModelQuery = function (Builder $query) {
|
||||||
if ($query->hasMacro('withTrashed')) {
|
// Remove all global scopes to prevent them from interfering with resource syncing
|
||||||
$query->withTrashed();
|
$query->withoutGlobalScopes();
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a central user with soft deletes
|
// Start with tenant1 and create a user that would be excluded by the scope
|
||||||
$centralUser = CentralUserWithSoftDeletes::create([
|
tenancy()->initialize($tenant1);
|
||||||
'global_id' => 'user',
|
|
||||||
'email' => 'user@test.cz',
|
// Create a tenant user that will sync to central
|
||||||
'name' => 'User',
|
TenantUser::create([
|
||||||
'password' => bcrypt('****'),
|
'global_id' => 'user123',
|
||||||
|
'name' => 'user123', // This will be stored in central
|
||||||
|
'email' => 'john@example.com',
|
||||||
|
'password' => 'password',
|
||||||
'role' => 'admin',
|
'role' => 'admin',
|
||||||
'foo' => 'bar',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$centralUser->tenants()->attach($tenant1);
|
|
||||||
|
|
||||||
// Soft delete the central user
|
|
||||||
$centralUser->delete();
|
|
||||||
|
|
||||||
// Try to create a tenant resource with the same global_id in tenant2
|
|
||||||
tenancy()->initialize($tenant2);
|
|
||||||
|
|
||||||
if (! $scopeGetModelQuery) {
|
|
||||||
// WITHOUT scopeGetModelQuery: syncing can't find the soft-deleted central user
|
|
||||||
// and tries to create a new one, violating the unique constraint on global_id
|
|
||||||
pest()->expectException(QueryException::class);
|
|
||||||
pest()->expectExceptionMessage('Duplicate entry');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a tenant resource - should sync with the existing soft-deleted central user
|
|
||||||
TenantUserWithSoftDeletes::create([
|
|
||||||
'global_id' => 'user',
|
|
||||||
'name' => 'Updated Name',
|
|
||||||
'email' => 'updated@example.com',
|
|
||||||
'password' => bcrypt('password'),
|
|
||||||
'role' => 'admin',
|
|
||||||
'foo' => 'bar',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
tenancy()->end();
|
tenancy()->end();
|
||||||
|
|
||||||
// With scopeGetModelQuery, verify the soft-deleted central user was found and updated
|
// Verify the central user was created
|
||||||
if ($scopeGetModelQuery) {
|
$centralUser = CentralUser::where('global_id', 'user123')->first();
|
||||||
$updatedCentralUser = CentralUserWithSoftDeletes::withTrashed()->where('global_id', 'user')->first();
|
expect($centralUser)->not->toBeNull();
|
||||||
|
|
||||||
expect($updatedCentralUser->name)->toBe('Updated Name');
|
// Now switch to tenant2 and try to update the same user using the scoped model
|
||||||
expect($updatedCentralUser->trashed())->toBeTrue(); // Still soft deleted
|
// The scoped model only shows users with null names, but we're about to give it a name
|
||||||
expect(CentralUserWithSoftDeletes::withTrashed()->where('global_id', 'user')->count())->toBe(1);
|
tenancy()->initialize($tenant2);
|
||||||
|
|
||||||
|
if (! $scopeGetModelQuery) {
|
||||||
|
// WITHOUT scopeGetModelQuery: The scope prevents finding the existing central user
|
||||||
|
// (whose name is null) after we update it to have a name, causing a duplicate key error
|
||||||
|
pest()->expectException(QueryException::class);
|
||||||
|
pest()->expectExceptionMessage('Duplicate entry');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to update the user with the scoped model - this gives it a name
|
||||||
|
TenantUserWithScope::create([
|
||||||
|
'global_id' => 'user123',
|
||||||
|
'name' => 'Jane', // This makes the central user invisible to the scope
|
||||||
|
'email' => 'jane@example.com',
|
||||||
|
'password' => 'password',
|
||||||
|
'role' => 'user',
|
||||||
|
]);
|
||||||
|
|
||||||
|
tenancy()->end();
|
||||||
|
|
||||||
|
if ($scopeGetModelQuery) {
|
||||||
|
// The scope was bypassed, the central user was found and updated
|
||||||
|
$updatedCentralUser = CentralUser::where('global_id', 'user123')->first();
|
||||||
|
expect($updatedCentralUser->name)->toBe('Jane'); // Synced from tenant
|
||||||
|
expect(CentralUser::where('global_id', 'user123')->count())->toBe(1); // Only one record
|
||||||
}
|
}
|
||||||
})->with([
|
})->with([
|
||||||
true,
|
true,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue