create(['name' => 'Member User']); WorkspaceMembership::factory()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'user_id' => (int) $member->getKey(), 'role' => 'readonly', ]); Livewire::actingAs($owner) ->test(TenantMembershipsRelationManager::class, [ 'ownerRecord' => $tenant, 'pageClass' => ManageTenantMemberships::class, ]) ->callTableAction('add_member', null, [ 'user_id' => $member->getKey(), 'role' => 'owner', ]); $membership = ManagedEnvironmentMembership::query() ->where('managed_environment_id', $tenant->getKey()) ->where('user_id', $member->getKey()) ->first(); expect($membership)->not->toBeNull(); expect($membership?->role)->toBe('readonly'); Livewire::actingAs($owner) ->test(TenantMembershipsRelationManager::class, [ 'ownerRecord' => $tenant, 'pageClass' => ManageTenantMemberships::class, ]) ->callTableAction('remove', $membership); expect(ManagedEnvironmentMembership::query()->whereKey($membership?->getKey())->exists())->toBeFalse(); }); it('hides scope management actions from readonly workspace members', function (): void { [$readonly, $tenant] = createUserWithTenant(role: 'readonly'); $member = User::factory()->create(); WorkspaceMembership::factory()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'user_id' => (int) $member->getKey(), 'role' => 'readonly', ]); $membership = ManagedEnvironmentMembership::query()->create([ 'managed_environment_id' => (int) $tenant->getKey(), 'user_id' => (int) $member->getKey(), 'role' => 'readonly', 'source' => 'manual', ]); Livewire::actingAs($readonly) ->test(TenantMembershipsRelationManager::class, [ 'ownerRecord' => $tenant, 'pageClass' => ManageTenantMemberships::class, ]) ->assertTableActionVisible('add_member') ->assertTableActionDisabled('add_member') ->assertTableActionVisible('remove', $membership) ->assertTableActionDisabled('remove', $membership); }); it('rejects role changes on explicit environment access scopes', function (): void { [$owner, $tenant] = createUserWithTenant(role: 'owner'); $membership = ManagedEnvironmentMembership::query() ->where('managed_environment_id', $tenant->getKey()) ->where('user_id', $owner->getKey()) ->firstOrFail(); expect(fn () => app(TenantMembershipManager::class)->changeRole($tenant, $owner, $membership, 'manager')) ->toThrow(DomainException::class, 'Managed-environment access scopes do not manage roles. Change the workspace role instead.'); });