generated from thegrind/laravel-dockerized
283 lines
10 KiB
PHP
283 lines
10 KiB
PHP
<?php
|
|
|
|
use App\Livewire\ManageUsers;
|
|
use App\Mail\InvitationMail;
|
|
use App\Models\Invitation;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Livewire\Livewire;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
// Create test users
|
|
$this->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,
|
|
]);
|
|
});
|
|
});
|
|
}); |