admin = User::factory()->create(['is_admin' => true]); $this->user = User::factory()->create(['is_admin' => false]); }); describe('ManageUsers Component', function () { describe('invitation creation', function () { it('allows admins to create invitations', function () { $this->actingAs($this->admin); Livewire::test(ManageUsers::class) ->set('invite_email', 'test@example.com') ->call('inviteUser') ->assertHasNoErrors(); $this->assertDatabaseHas('invitations', [ 'email' => 'test@example.com', 'invited_by' => $this->admin->id, ]); }); it('prevents non-admins from creating invitations', function () { // Test authorization at the method level without rendering view $this->actingAs($this->user); $component = new ManageUsers(); $component->invite_email = 'test@example.com'; $this->expectException(\Illuminate\Auth\Access\AuthorizationException::class); $component->inviteUser(); }); it('validates email format when creating invitations', function () { $this->actingAs($this->admin); Livewire::test(ManageUsers::class) ->set('invite_email', 'invalid-email') ->call('inviteUser') ->assertHasErrors('invite_email'); }); it('generates a random code and sets expiration when creating invitations', function () { $this->actingAs($this->admin); Livewire::test(ManageUsers::class) ->set('invite_email', 'test@example.com') ->call('inviteUser'); $invitation = Invitation::where('email', 'test@example.com')->first(); expect($invitation->code)->toHaveLength(50); expect($invitation->expires_at)->not()->toBeNull(); expect($invitation->invited_by)->toBe($this->admin->id); }); }); describe('email sending', function () { it('sends email when checkbox is checked', function () { Mail::fake(); $this->actingAs($this->admin); Livewire::test(ManageUsers::class) ->set('invite_email', 'test@example.com') ->set('send_email', true) ->call('inviteUser'); $invitation = Invitation::where('email', 'test@example.com')->first(); Mail::assertSent(InvitationMail::class, function ($mail) use ($invitation) { return $mail->hasTo('test@example.com') && $mail->invitation->id === $invitation->id; }); }); it('does not send email when checkbox is unchecked', function () { Mail::fake(); $this->actingAs($this->admin); Livewire::test(ManageUsers::class) ->set('invite_email', 'test@example.com') ->set('send_email', false) ->call('inviteUser'); Mail::assertNotSent(InvitationMail::class); }); it('sends email to the correct recipient', function () { Mail::fake(); $this->actingAs($this->admin); $testEmail = 'specific@example.com'; Livewire::test(ManageUsers::class) ->set('invite_email', $testEmail) ->set('send_email', true) ->call('inviteUser'); Mail::assertSent(InvitationMail::class, function ($mail) use ($testEmail) { return $mail->hasTo($testEmail); }); Mail::assertNotSent(InvitationMail::class, function ($mail) { return $mail->hasTo('wrong@example.com'); }); }); }); describe('invitation deletion', function () { it('allows admins to delete pending invitations', function () { $this->actingAs($this->admin); $invitation = Invitation::factory()->create([ 'accepted_at' => null, // Pending invitation ]); Livewire::test(ManageUsers::class) ->call('deleteInvitation', $invitation) ->assertHasNoErrors(); $this->assertDatabaseMissing('invitations', [ 'id' => $invitation->id, ]); }); it('prevents non-admins from deleting invitations', function () { // Test authorization at the method level without rendering view $this->actingAs($this->user); $invitation = Invitation::factory()->create([ 'accepted_at' => null, ]); $component = new ManageUsers(); $this->expectException(\Illuminate\Auth\Access\AuthorizationException::class); $component->deleteInvitation($invitation); }); it('prevents deletion of accepted invitations', function () { $this->actingAs($this->admin); $invitation = Invitation::factory()->create([ 'accepted_at' => now(), // Accepted invitation ]); Livewire::test(ManageUsers::class) ->call('deleteInvitation', $invitation) ->assertHasNoErrors(); // Component handles this gracefully // Invitation should still exist $this->assertDatabaseHas('invitations', [ 'id' => $invitation->id, ]); }); }); describe('component state management', function () { it('resets form fields after successful invitation creation', function () { $this->actingAs($this->admin); $component = Livewire::test(ManageUsers::class) ->set('invite_email', 'test@example.com') ->set('send_email', true) ->call('inviteUser'); expect($component->get('invite_email'))->toBe(''); expect($component->get('send_email'))->toBe(false); }); it('updates invitations collection after creation', function () { $this->actingAs($this->admin); $component = Livewire::test(ManageUsers::class); $initialCount = $component->get('invitations')->count(); $component ->set('invite_email', 'test@example.com') ->call('inviteUser'); expect($component->get('invitations')->count())->toBe($initialCount + 1); }); it('shows success message after invitation creation', function () { $this->actingAs($this->admin); Livewire::test(ManageUsers::class) ->set('invite_email', 'test@example.com') ->set('send_email', false) ->call('inviteUser') ->assertHasNoErrors(); // Verify the invitation was created $this->assertDatabaseHas('invitations', [ 'email' => 'test@example.com', ]); }); it('tracks email sending status correctly', function () { Mail::fake(); $this->actingAs($this->admin); Livewire::test(ManageUsers::class) ->set('invite_email', 'test@example.com') ->set('send_email', true) ->call('inviteUser') ->assertHasNoErrors(); // Verify the invitation was created $this->assertDatabaseHas('invitations', [ 'email' => 'test@example.com', ]); // Verify email was sent Mail::assertSent(InvitationMail::class); }); }); describe('authorization integration', function () { it('loads data for admin users', function () { $this->actingAs($this->admin); $adminComponent = Livewire::test(ManageUsers::class); expect($adminComponent->get('users'))->not()->toBeNull(); expect($adminComponent->get('invitations'))->not()->toBeNull(); }); }); describe('user role management', function () { it('allows admins to change user roles', function () { $this->actingAs($this->admin); $targetUser = User::factory()->create(['is_admin' => false]); Livewire::test(ManageUsers::class) ->call('changeUserRole', $targetUser, 'admin') ->assertHasNoErrors(); expect($targetUser->fresh()->is_admin)->toBe(true); }); it('prevents admins from demoting themselves', function () { $this->actingAs($this->admin); Livewire::test(ManageUsers::class) ->call('changeUserRole', $this->admin, 'user') ->assertHasNoErrors(); // Verify the admin status wasn't changed expect($this->admin->fresh()->is_admin)->toBe(true); }); it('allows admins to delete other users', function () { $this->actingAs($this->admin); $targetUser = User::factory()->create(); Livewire::test(ManageUsers::class) ->call('deleteUser', $targetUser) ->assertHasNoErrors(); $this->assertDatabaseMissing('users', [ 'id' => $targetUser->id, ]); }); }); });