330 lines
12 KiB
PHP
330 lines
12 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\User;
|
|
use Tests\DatabaseTestCase;
|
|
|
|
class UserManagementTest extends DatabaseTestCase
|
|
{
|
|
private User $superadmin;
|
|
private User $dokter;
|
|
private User $apoteker;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
$this->superadmin = User::factory()->create(['role' => 'superadmin']);
|
|
$this->dokter = User::factory()->create(['role' => 'dokter', 'name' => 'Dr. Budi']);
|
|
$this->apoteker = User::factory()->create(['role' => 'apoteker', 'name' => 'Apt. Siti']);
|
|
}
|
|
|
|
// ─────────────────────────────────────────
|
|
// Akses: hanya superadmin
|
|
// ─────────────────────────────────────────
|
|
|
|
public function test_superadmin_can_access_index(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
$response = $this->get(route('user-management.index'));
|
|
$response->assertStatus(200);
|
|
}
|
|
|
|
public function test_dokter_cannot_access_index(): void
|
|
{
|
|
$this->actingAs($this->dokter);
|
|
$response = $this->get(route('user-management.index'));
|
|
$response->assertStatus(403);
|
|
}
|
|
|
|
public function test_apoteker_cannot_access_index(): void
|
|
{
|
|
$this->actingAs($this->apoteker);
|
|
$response = $this->get(route('user-management.index'));
|
|
$response->assertStatus(403);
|
|
}
|
|
|
|
public function test_guest_is_redirected_to_login(): void
|
|
{
|
|
$response = $this->get(route('user-management.index'));
|
|
$response->assertRedirect(route('login'));
|
|
}
|
|
|
|
// ─────────────────────────────────────────
|
|
// index — filter & search
|
|
// ─────────────────────────────────────────
|
|
|
|
public function test_index_does_not_show_superadmin_users(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
$response = $this->get(route('user-management.index'));
|
|
$response->assertDontSee($this->superadmin->email);
|
|
$response->assertSee('Dr. Budi');
|
|
}
|
|
|
|
public function test_index_search_by_name(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
$response = $this->get(route('user-management.index', ['search' => 'Budi']));
|
|
$response->assertSee('Dr. Budi');
|
|
$response->assertDontSee('Apt. Siti');
|
|
}
|
|
|
|
public function test_index_filter_by_role(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
$response = $this->get(route('user-management.index', ['role' => 'dokter']));
|
|
$response->assertSee('Dr. Budi');
|
|
$response->assertDontSee('Apt. Siti');
|
|
}
|
|
|
|
// ─────────────────────────────────────────
|
|
// create & store
|
|
// ─────────────────────────────────────────
|
|
|
|
public function test_superadmin_can_access_create_page(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
$response = $this->get(route('user-management.create'));
|
|
$response->assertStatus(200);
|
|
}
|
|
|
|
public function test_store_creates_new_dokter(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
|
|
$response = $this->post(route('user-management.store'), [
|
|
'name' => 'Dr. Andi',
|
|
'email' => 'andi@example.com',
|
|
'role' => 'dokter',
|
|
'password' => 'password123',
|
|
'password_confirmation' => 'password123',
|
|
]);
|
|
|
|
$response->assertRedirect(route('user-management.index'));
|
|
$response->assertSessionHas('success');
|
|
$this->assertDatabaseHas('users', [
|
|
'email' => 'andi@example.com',
|
|
'role' => 'dokter',
|
|
]);
|
|
}
|
|
|
|
public function test_store_creates_new_apoteker(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
|
|
$response = $this->post(route('user-management.store'), [
|
|
'name' => 'Apt. Rina',
|
|
'email' => 'rina@example.com',
|
|
'role' => 'apoteker',
|
|
'password' => 'password123',
|
|
'password_confirmation' => 'password123',
|
|
]);
|
|
|
|
$response->assertRedirect(route('user-management.index'));
|
|
$this->assertDatabaseHas('users', [
|
|
'email' => 'rina@example.com',
|
|
'role' => 'apoteker',
|
|
]);
|
|
}
|
|
|
|
public function test_store_fails_without_required_fields(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
|
|
$response = $this->post(route('user-management.store'), []);
|
|
$response->assertSessionHasErrors(['name', 'email', 'role', 'password']);
|
|
}
|
|
|
|
public function test_store_fails_with_duplicate_email(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
|
|
$response = $this->post(route('user-management.store'), [
|
|
'name' => 'Duplicate',
|
|
'email' => $this->dokter->email,
|
|
'role' => 'dokter',
|
|
'password' => 'password123',
|
|
'password_confirmation' => 'password123',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('email');
|
|
}
|
|
|
|
public function test_store_cannot_create_superadmin_role(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
|
|
$response = $this->post(route('user-management.store'), [
|
|
'name' => 'Fake Admin',
|
|
'email' => 'fake@example.com',
|
|
'role' => 'superadmin',
|
|
'password' => 'password123',
|
|
'password_confirmation' => 'password123',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('role');
|
|
$this->assertDatabaseMissing('users', ['email' => 'fake@example.com']);
|
|
}
|
|
|
|
// ─────────────────────────────────────────
|
|
// edit & update
|
|
// ─────────────────────────────────────────
|
|
|
|
public function test_superadmin_can_access_edit_page(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
$response = $this->get(route('user-management.edit', $this->dokter));
|
|
$response->assertStatus(200);
|
|
}
|
|
|
|
public function test_edit_superadmin_user_returns_403(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
$otherAdmin = User::factory()->create(['role' => 'superadmin']);
|
|
|
|
$response = $this->get(route('user-management.edit', $otherAdmin));
|
|
$response->assertStatus(403);
|
|
}
|
|
|
|
public function test_update_changes_user_data(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
|
|
$response = $this->put(route('user-management.update', $this->dokter), [
|
|
'name' => 'Dr. Budi Updated',
|
|
'email' => $this->dokter->email,
|
|
'role' => 'dokter',
|
|
]);
|
|
|
|
$response->assertRedirect(route('user-management.index'));
|
|
$response->assertSessionHas('success');
|
|
$this->assertEquals('Dr. Budi Updated', $this->dokter->fresh()->name);
|
|
}
|
|
|
|
public function test_update_can_change_role(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
|
|
$response = $this->put(route('user-management.update', $this->dokter), [
|
|
'name' => $this->dokter->name,
|
|
'email' => $this->dokter->email,
|
|
'role' => 'apoteker',
|
|
]);
|
|
|
|
$response->assertRedirect(route('user-management.index'));
|
|
$this->assertEquals('apoteker', $this->dokter->fresh()->role);
|
|
}
|
|
|
|
public function test_update_without_password_keeps_old_password(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
$oldPassword = $this->dokter->password;
|
|
|
|
$this->put(route('user-management.update', $this->dokter), [
|
|
'name' => $this->dokter->name,
|
|
'email' => $this->dokter->email,
|
|
'role' => 'dokter',
|
|
]);
|
|
|
|
$this->assertEquals($oldPassword, $this->dokter->fresh()->password);
|
|
}
|
|
|
|
public function test_update_with_new_password_changes_password(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
$oldPassword = $this->dokter->password;
|
|
|
|
$this->put(route('user-management.update', $this->dokter), [
|
|
'name' => $this->dokter->name,
|
|
'email' => $this->dokter->email,
|
|
'role' => 'dokter',
|
|
'password' => 'newpassword123',
|
|
'password_confirmation' => 'newpassword123',
|
|
]);
|
|
|
|
$this->assertNotEquals($oldPassword, $this->dokter->fresh()->password);
|
|
}
|
|
|
|
public function test_update_superadmin_user_returns_403(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
$otherAdmin = User::factory()->create(['role' => 'superadmin']);
|
|
|
|
$response = $this->put(route('user-management.update', $otherAdmin), [
|
|
'name' => 'Hacked',
|
|
'email' => $otherAdmin->email,
|
|
'role' => 'dokter',
|
|
]);
|
|
|
|
$response->assertStatus(403);
|
|
}
|
|
|
|
// ─────────────────────────────────────────
|
|
// destroy
|
|
// ─────────────────────────────────────────
|
|
|
|
public function test_destroy_deletes_user(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
$userId = $this->dokter->id;
|
|
|
|
$response = $this->delete(route('user-management.destroy', $this->dokter));
|
|
|
|
$response->assertRedirect(route('user-management.index'));
|
|
$response->assertSessionHas('success');
|
|
$this->assertDatabaseMissing('users', ['id' => $userId]);
|
|
}
|
|
|
|
public function test_destroy_cannot_delete_superadmin(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
$otherAdmin = User::factory()->create(['role' => 'superadmin']);
|
|
|
|
$response = $this->delete(route('user-management.destroy', $otherAdmin));
|
|
$response->assertStatus(403);
|
|
$this->assertDatabaseHas('users', ['id' => $otherAdmin->id]);
|
|
}
|
|
|
|
public function test_destroy_cannot_delete_self(): void
|
|
{
|
|
$this->actingAs($this->superadmin);
|
|
|
|
$response = $this->delete(route('user-management.destroy', $this->superadmin));
|
|
|
|
$response->assertRedirect(route('user-management.index'));
|
|
$response->assertSessionHas('error');
|
|
$this->assertDatabaseHas('users', ['id' => $this->superadmin->id]);
|
|
}
|
|
|
|
// ─────────────────────────────────────────
|
|
// Non-superadmin cannot store/update/destroy
|
|
// ─────────────────────────────────────────
|
|
|
|
public function test_dokter_cannot_store_user(): void
|
|
{
|
|
$this->actingAs($this->dokter);
|
|
|
|
$response = $this->post(route('user-management.store'), [
|
|
'name' => 'Unauthorized',
|
|
'email' => 'unauth@example.com',
|
|
'role' => 'dokter',
|
|
'password' => 'password123',
|
|
'password_confirmation' => 'password123',
|
|
]);
|
|
|
|
$response->assertStatus(403);
|
|
$this->assertDatabaseMissing('users', ['email' => 'unauth@example.com']);
|
|
}
|
|
|
|
public function test_apoteker_cannot_delete_user(): void
|
|
{
|
|
$this->actingAs($this->apoteker);
|
|
|
|
$response = $this->delete(route('user-management.destroy', $this->dokter));
|
|
$response->assertStatus(403);
|
|
$this->assertDatabaseHas('users', ['id' => $this->dokter->id]);
|
|
}
|
|
}
|