create(); $workspace = Workspace::factory()->create(); $userToDetach = User::factory()->create(); $workspace->users()->attach($admin, ['role' => 'admin']); $workspace->users()->attach($userToDetach, ['role' => 'member']); expect($userToDetach->workspaces()->count())->toBe(1); // Act: Admin detaches the user $this->actingAs($admin) ->deleteJson(route('open.workspaces.users.remove', ['workspaceId' => $workspace->id, 'userId' => $userToDetach->id])) ->assertOk(); // Assert: User now has 1 workspace, named 'My Workspace' $userToDetach->refresh(); expect($userToDetach->workspaces()->count())->toBe(1); // Check workspace name $newWorkspace = $userToDetach->workspaces()->first(); expect($newWorkspace->name)->toBe('My Workspace'); // Check role by querying the pivot table directly $pivotData = DB::table('user_workspace') ->where('user_id', $userToDetach->id) ->where('workspace_id', $newWorkspace->id) ->first(); expect($pivotData->role)->toBe('admin'); }); test('detaching user from one workspace when they have others does not create default one via controller', function () { // Arrange: User with two workspaces, acting user is admin $admin = User::factory()->create(); $workspace1 = Workspace::factory()->create(); $workspace2 = Workspace::factory()->create(); $userToDetach = User::factory()->create(); $workspace1->users()->attach($admin, ['role' => 'admin']); $workspace1->users()->attach($userToDetach, ['role' => 'member']); $workspace2->users()->attach($userToDetach, ['role' => 'member']); // User belongs to a second workspace expect($userToDetach->workspaces()->count())->toBe(2); $initialWorkspaceIds = $userToDetach->workspaces()->pluck('workspaces.id')->toArray(); // Act: Admin detaches the user from workspace1 $this->actingAs($admin) ->deleteJson(route('open.workspaces.users.remove', ['workspaceId' => $workspace1->id, 'userId' => $userToDetach->id])) ->assertOk(); // Assert: User now has 1 workspace (workspace2), no default created $userToDetach->refresh(); expect($userToDetach->workspaces()->count())->toBe(1); $remainingWorkspace = $userToDetach->workspaces()->first(); expect($remainingWorkspace->id)->toBe($workspace2->id); expect($userToDetach->workspaces()->where('name', 'My Workspace')->exists())->toBeFalse(); expect($userToDetach->workspaces()->pluck('workspaces.id')->toArray())->not->toContain($workspace1->id); }); test('user leaving last workspace creates a default one', function () { // Arrange: User with one workspace $workspace = Workspace::factory()->create(); $user = User::factory()->create(); $workspace->users()->attach($user, ['role' => 'member']); // Can be any role to leave expect($user->workspaces()->count())->toBe(1); // Act: User leaves the workspace $this->actingAs($user) ->postJson(route('open.workspaces.leave', ['workspaceId' => $workspace->id])) ->assertOk(); // Assert: User now has 1 workspace, named 'My Workspace' $user->refresh(); expect($user->workspaces()->count())->toBe(1); // Check workspace name $newWorkspace = $user->workspaces()->first(); expect($newWorkspace->name)->toBe('My Workspace'); // Check role by querying the pivot table directly $pivotData = DB::table('user_workspace') ->where('user_id', $user->id) ->where('workspace_id', $newWorkspace->id) ->first(); expect($pivotData->role)->toBe('admin'); }); test('user leaving one workspace when they have others does not create default one', function () { // Arrange: User with two workspaces $workspace1 = Workspace::factory()->create(); $workspace2 = Workspace::factory()->create(); $user = User::factory()->create(); $workspace1->users()->attach($user, ['role' => 'member']); $workspace2->users()->attach($user, ['role' => 'member']); expect($user->workspaces()->count())->toBe(2); // Act: User leaves workspace1 $this->actingAs($user) ->postJson(route('open.workspaces.leave', ['workspaceId' => $workspace1->id])) ->assertOk(); // Assert: User now has 1 workspace (workspace2), no default created $user->refresh(); expect($user->workspaces()->count())->toBe(1); $remainingWorkspace = $user->workspaces()->first(); expect($remainingWorkspace->id)->toBe($workspace2->id); expect($user->workspaces()->where('name', 'My Workspace')->exists())->toBeFalse(); }); // Tests for RemoveWorkspaceGuests job test('removing guest from last workspace via job creates a default one', function () { // Arrange: Guest user with one workspace (the one they'll be removed from), Admin user $admin = User::factory()->create(); $workspace = Workspace::factory()->create(); $guest = User::factory()->create(); $workspace->users()->attach($admin, ['role' => 'admin']); $workspace->users()->attach($guest, ['role' => 'guest']); expect($guest->workspaces()->count())->toBe(1); // Act: Dispatch the job to remove guests from the workspace // Pass the admin user as required by the job constructor RemoveWorkspaceGuests::dispatchSync($admin, $workspace); // Fixed: Job expects User first, then additional param // Assert: Guest user now has 1 workspace, named 'My Workspace' $guest->refresh(); expect($guest->workspaces()->count())->toBe(1); // Check workspace name $newWorkspace = $guest->workspaces()->first(); expect($newWorkspace->name)->toBe('My Workspace'); // Check role by querying the pivot table directly $pivotData = DB::table('user_workspace') ->where('user_id', $guest->id) ->where('workspace_id', $newWorkspace->id) ->first(); expect($pivotData->role)->toBe('admin'); }); test('removing guest from one workspace when they have others via job does not create default one', function () { // Arrange: Guest user with two workspaces, Admin user $admin = User::factory()->create(); $workspaceToRemoveFrom = Workspace::factory()->create(); $otherWorkspace = Workspace::factory()->create(); $guest = User::factory()->create(); $workspaceToRemoveFrom->users()->attach($admin, ['role' => 'admin']); $workspaceToRemoveFrom->users()->attach($guest, ['role' => 'guest']); $otherWorkspace->users()->attach($guest, ['role' => 'member']); // Belongs to another workspace expect($guest->workspaces()->count())->toBe(2); // Act: Dispatch the job to remove guests from the first workspace // Pass the admin user as required by the job constructor RemoveWorkspaceGuests::dispatchSync($admin, $workspaceToRemoveFrom); // Fixed: Job expects User first, then additional param // Assert: Guest user now has 1 workspace (the other one), no default created $guest->refresh(); expect($guest->workspaces()->count())->toBe(1); $remainingWorkspace = $guest->workspaces()->first(); expect($remainingWorkspace->id)->toBe($otherWorkspace->id); expect($guest->workspaces()->where('name', 'My Workspace')->exists())->toBeFalse(); }); test('ensures user with no workspaces gets a default one', function () { // Arrange: Create user without any workspaces $user = User::factory()->create(); expect($user->workspaces()->count())->toBe(0); // Create a controller that uses the trait $controller = new class () { use \App\Traits\EnsureUserHasWorkspace; public function ensureWorkspace(User $user) { $this->ensureUserHasWorkspace($user); } }; // Act: Call the trait method $controller->ensureWorkspace($user); // Assert: User now has a workspace $user->refresh(); expect($user->workspaces()->count())->toBe(1); // Check workspace properties $newWorkspace = $user->workspaces()->first(); expect($newWorkspace->name)->toBe('My Workspace'); // Check role $pivotData = DB::table('user_workspace') ->where('user_id', $user->id) ->where('workspace_id', $newWorkspace->id) ->first(); expect($pivotData->role)->toBe('admin'); });