Export to Excel
Add User
diff --git a/tests/Feature/UsersControllerTest.php b/tests/Feature/UsersControllerTest.php
new file mode 100644
index 0000000..0a1f021
--- /dev/null
+++ b/tests/Feature/UsersControllerTest.php
@@ -0,0 +1,466 @@
+ 'usermanagement',
+ 'slug' => 'usermanagement'
+ ]);
+
+ // Create usermanagement.read permission
+ Permission::create([
+ 'name' => 'usermanagement.read',
+ 'guard_name' => 'web',
+ 'permission_group_id' => $permissionGroup->id
+ ]);
+
+ // Create role with usermanagement.read permission
+ $this->adminRole = Role::create(['name' => 'admin', 'guard_name' => 'web']);
+ $this->adminRole->givePermissionTo('usermanagement.read');
+
+ // Create a user with admin role
+ // Create a user for testing
+ $this->user = User::factory()->create([
+ 'name' => 'Original Name',
+ 'email' => 'original@example.com',
+ 'nik' => '123456',
+ 'sign' => 'old-signature.jpg'
+ ]);
+
+ // Mock the storage
+ Storage::fake('public');
+ $this->user->assignRole($this->adminRole);
+
+ // Create test role for assignment to new user
+ Role::create(['name' => 'operator', 'guard_name' => 'web']);
+
+ }
+
+ #[Test]
+ public function should_display_users_index_page_when_user_has_users_view_permission()
+ {
+ $response = $this->actingAs($this->user)
+ ->get(route('users.index'));
+
+ $response->assertStatus(200);
+ $response->assertViewIs('usermanagement::users.index');
+ }
+
+ #[Test]
+ public function should_return_json_response_with_correct_pagination_data_for_datatables()
+ {
+ // Create some test users
+ $testUsers = User::factory()->count(15)->create();
+
+ // Set up the request parameters
+ $requestData = [
+ 'draw' => 1,
+ 'page' => 1, // Changed from 2 to 1 to match the controller logic
+ 'size' => 5,
+ 'search' => '',
+ 'sortField' => 'name',
+ 'sortOrder' => 'asc'
+ ];
+
+ // Make the request
+ $response = $this->actingAs($this->user)
+ ->getJson(route('users.datatables') . '?' . http_build_query($requestData));
+
+ // Assert response status and structure
+ $response->assertStatus(200);
+ $response->assertJsonStructure([
+ 'draw',
+ 'recordsTotal',
+ 'recordsFiltered',
+ 'pageCount',
+ 'page',
+ 'totalCount',
+ 'data'
+ ]);
+
+ // Get total count of users for verification (16 = 15 created + 1 from setup)
+ $totalUsers = User::count();
+
+ // Verify the pagination data
+ $responseData = $response->json();
+ $this->assertEquals(1, $responseData['draw']);
+ $this->assertEquals($totalUsers, $responseData['recordsTotal']);
+ $this->assertEquals($totalUsers, $responseData['recordsFiltered']);
+ $this->assertEquals(ceil($totalUsers / $requestData['size']), $responseData['pageCount']);
+ $this->assertEquals($requestData['page'], $responseData['page']);
+
+ // Verify that we have the correct number of users in the response
+ $this->assertCount(5, $responseData['data']);
+
+ // Verify that the data is ordered correctly - get first page of sorted data
+ $this->assertEquals(
+ User::orderBy('name', 'asc')->take(5)->pluck('id')->toArray(),
+ collect($responseData['data'])->pluck('id')->toArray()
+ );
+ }
+
+ #[Test]
+ public function should_filter_users_by_search_term_when_search_parameter_is_provided()
+ {
+ // Create test users with specific names for testing search
+ $matchingUser1 = User::factory()->create(['name' => 'Test User One']);
+ $matchingUser2 = User::factory()->create(['email' => 'test@example.com']);
+ $nonMatchingUser = User::factory()->create(['name' => 'Different User', 'email' => 'different@example.com']);
+
+ // Set up the request parameters with search term
+ $requestData = [
+ 'draw' => 1,
+ 'page' => 1,
+ 'size' => 10,
+ 'search' => 'test',
+ 'sortField' => 'name',
+ 'sortOrder' => 'asc'
+ ];
+
+ // Make the request
+ $response = $this->actingAs($this->user)
+ ->getJson(route('users.datatables') . '?' . http_build_query($requestData));
+
+ // Assert response status and structure
+ $response->assertStatus(200);
+ $response->assertJsonStructure([
+ 'draw',
+ 'recordsTotal',
+ 'recordsFiltered',
+ 'pageCount',
+ 'page',
+ 'totalCount',
+ 'data'
+ ]);
+
+ // Get the response data
+ $responseData = $response->json();
+
+ // Verify that only matching users are returned
+ $this->assertEquals(2, $responseData['recordsFiltered']);
+
+ // Extract user IDs from the response
+ $returnedUserIds = collect($responseData['data'])->pluck('id')->toArray();
+
+ // Verify the correct users are returned
+ $this->assertContains($matchingUser1->id, $returnedUserIds);
+ $this->assertContains($matchingUser2->id, $returnedUserIds);
+ $this->assertNotContains($nonMatchingUser->id, $returnedUserIds);
+ }
+
+ #[Test]
+ public function should_correctly_sort_users_when_sortField_and_sortOrder_parameters_are_specified()
+ {
+ // Create test users with varying names to test different sort orders
+ $userA = User::factory()->create(['name' => 'Adam Smith']);
+ $userB = User::factory()->create(['name' => 'Brian Jones']);
+ $userC = User::factory()->create(['name' => 'Charlie Brown']);
+
+ // Test ascending order
+ $requestDataAsc = [
+ 'draw' => 1,
+ 'page' => 1,
+ 'size' => 10,
+ 'search' => '',
+ 'sortField' => 'name',
+ 'sortOrder' => 'asc'
+ ];
+
+ $responseAsc = $this->actingAs($this->user)
+ ->getJson(route('users.datatables') . '?' . http_build_query($requestDataAsc));
+
+ $responseAsc->assertStatus(200);
+ $responseDataAsc = $responseAsc->json();
+
+ // Check if sorted ascending by name
+ $userIdsAsc = collect($responseDataAsc['data'])->pluck('id')->toArray();
+ $expectedOrderAsc = User::orderBy('name', 'asc')->pluck('id')->toArray();
+ $this->assertEquals($expectedOrderAsc, $userIdsAsc);
+
+ // Test descending order
+ $requestDataDesc = [
+ 'draw' => 1,
+ 'page' => 1,
+ 'size' => 10,
+ 'search' => '',
+ 'sortField' => 'name',
+ 'sortOrder' => 'desc'
+ ];
+
+ $responseDesc = $this->actingAs($this->user)
+ ->getJson(route('users.datatables') . '?' . http_build_query($requestDataDesc));
+
+ $responseDesc->assertStatus(200);
+ $responseDataDesc = $responseDesc->json();
+
+ // Check if sorted descending by name
+ $userIdsDesc = collect($responseDataDesc['data'])->pluck('id')->toArray();
+ $expectedOrderDesc = User::orderBy('name', 'desc')->pluck('id')->toArray();
+ $this->assertEquals($expectedOrderDesc, $userIdsDesc);
+
+ // Test sorting by a different field (email)
+ $requestDataEmail = [
+ 'draw' => 1,
+ 'page' => 1,
+ 'size' => 10,
+ 'search' => '',
+ 'sortField' => 'email',
+ 'sortOrder' => 'asc'
+ ];
+
+ $responseEmail = $this->actingAs($this->user)
+ ->getJson(route('users.datatables') . '?' . http_build_query($requestDataEmail));
+
+ $responseEmail->assertStatus(200);
+ $responseDataEmail = $responseEmail->json();
+
+ // Check if sorted by email
+ $userIdsEmail = collect($responseDataEmail['data'])->pluck('id')->toArray();
+ $expectedOrderEmail = User::orderBy('email', 'asc')->pluck('id')->toArray();
+ $this->assertEquals($expectedOrderEmail, $userIdsEmail);
+ }
+
+ #[Test]
+ public function should_successfully_create_a_new_user_and_assign_roles_when_valid_data_is_submitted()
+ {
+ // Prepare valid user data
+ $userData = [
+ 'name' => 'Test User',
+ 'email' => 'test@example.com',
+ 'password' => 'password123',
+ 'password_confirmation' => 'password123',
+ 'nik' => '789234',
+ 'roles' => ['operator']
+ ];
+
+ // Submit the request to create a new user
+ $response = $this->actingAs($this->user)
+ ->post(route('users.store'), $userData);
+
+ // Assert redirect to users index page with success message
+ $response->assertRedirect(route('users.index'));
+ $response->assertSessionHas('success', 'User created successfully.');
+
+ // Assert the user was created in the database
+ $this->assertDatabaseHas('users', [
+ 'name' => 'Test User',
+ 'email' => 'test@example.com',
+ 'nik' => '789234'
+ ]);
+
+ // Assert the user was assigned the correct role
+ $newUser = User::where('email', 'test@example.com')->first();
+ $this->assertTrue($newUser->hasRole('operator'));
+ }
+
+ #[Test]
+ public function should_successfully_update_existing_user_information_and_role_assignments()
+ {
+ // Create a test user with admin role
+ $userToUpdate = User::factory()->create([
+ 'name' => 'Original Name',
+ 'email' => 'originalee@example.com',
+ 'nik' => '987654'
+ ]);
+ $userToUpdate->assignRole($this->adminRole);
+
+ // Create an additional role for the update test
+ $newRole = Role::create(['name' => 'editor', 'guard_name' => 'web']);
+
+ // Prepare update data
+ $updateData = [
+ 'name' => 'Updated Name',
+ 'email' => 'updated@example.com',
+ 'nik' => '654321',
+ 'roles' => ['operator'] // Change role from admin to operator
+ ];
+
+ // Make the request to update the user
+ $response = $this->actingAs($this->user)
+ ->put(route('users.update', $userToUpdate->id), $updateData);
+
+ // Assert redirect to users index page with success message
+ $response->assertRedirect(route('users.index'));
+ $response->assertSessionHas('success', 'User updated successfully.');
+
+ // Assert the user was updated in the database
+ $this->assertDatabaseHas('users', [
+ 'id' => $userToUpdate->id,
+ 'name' => 'Updated Name',
+ 'email' => 'updated@example.com',
+ 'nik' => '654321'
+ ]);
+
+ // Refresh the user model from database
+ $userToUpdate->refresh();
+
+ // Assert the user has the new role and doesn't have the old role
+ $this->assertTrue($userToUpdate->hasRole('operator'));
+ $this->assertFalse($userToUpdate->hasRole('admin'));
+ }
+
+ #[Test]
+ public function should_delete_a_user_when_the_authenticated_user_has_users_delete_permission()
+ {
+ // Create the permission for delete users
+ $permissionGroup = PermissionGroup::create([
+ 'name' => 'usermanagement',
+ 'slug' => 'usermanagement'
+ ]);
+
+ // Create delete permission
+ Permission::create([
+ 'name' => 'usermanagement.delete',
+ 'guard_name' => 'web',
+ 'permission_group_id' => $permissionGroup->id
+ ]);
+
+ // Create role with delete permission
+ $role = Role::create(['name' => 'manager', 'guard_name' => 'web']);
+ $role->givePermissionTo('usermanagement.delete');
+
+ // Create an admin user with the role that has delete permission
+ $adminUser = User::factory()->create();
+ $adminUser->assignRole($role);
+
+ // Create a user to be deleted
+ $userToDelete = User::factory()->create();
+
+ // Make the request to delete the user
+ $response = $this->actingAs($adminUser)
+ ->delete(route('users.destroy', $userToDelete->id));
+
+ // Assert the response is correct
+ $decodedResponse = json_decode($response->getContent(), true);
+ $this->assertEquals('User deleted successfully.', $decodedResponse['message']);
+ $this->assertTrue($decodedResponse['success']);
+
+ // Assert the user was soft deleted
+ $this->assertSoftDeleted('users', ['id' => $userToDelete->id]);
+ }
+
+ #[Test]
+ public function should_restore_a_soft_deleted_user_when_the_authenticated_user_has_users_restore_permission()
+ {
+ // Create permission group
+ $permissionGroup = PermissionGroup::create([
+ 'name' => 'usermanagement',
+ 'slug' => 'usermanagement'
+ ]);
+
+ // Create restore permission
+ Permission::create([
+ 'name' => 'usermanagement.restore',
+ 'guard_name' => 'web',
+ 'permission_group_id' => $permissionGroup->id
+ ]);
+
+ // Create role with restore permission
+ $role = Role::create(['name' => 'restorer', 'guard_name' => 'web']);
+ $role->givePermissionTo('usermanagement.restore');
+
+ // Create an admin user with the role that has restore permission
+ $adminUser = User::factory()->create();
+ $adminUser->assignRole($role);
+
+ // Create a user to be restored
+ $userToRestore = User::factory()->create();
+ $userToRestore->delete(); // Soft delete the user
+
+ // Verify the user is soft-deleted
+ $this->assertSoftDeleted('users', ['id' => $userToRestore->id]);
+
+ // Make the request to restore the user
+ $response = $this->actingAs($adminUser)
+ ->get(route('users.restore', $userToRestore->id));
+
+ // Assert the response redirects to users.index with success message
+ $response->assertRedirect(route('users.index'));
+ $response->assertSessionHas('success', 'User restored successfully.');
+
+ // Assert the user was restored
+ $this->assertDatabaseHas('users', [
+ 'id' => $userToRestore->id,
+ 'deleted_at' => null
+ ]);
+ }
+
+ #[Test]
+ public function should_update_users_profile_including_signature_image_when_valid_data_is_submitted()
+ {
+ // Create a fake signature file
+ $file = UploadedFile::fake()->image('new-signature.jpg');
+
+ // Create a fake old signature file in storage
+ Storage::disk('public')->put(
+ 'signatures/' . $this->user->id . '/old-signature.jpg',
+ 'fake content'
+ );
+
+ // Prepare valid profile data with new signature
+ $profileData = [
+ 'name' => 'Updated Name',
+ 'email' => 'updated@example.com',
+ 'nik' => '654321',
+ 'sign' => $file
+ ];
+
+ // Make the request to update the profile
+ $response = $this->actingAs($this->user)
+ ->put(route('users.update-profile'), $profileData);
+
+ // Assert redirect to profile page with success message
+ $response->assertRedirect(route('users.profile'));
+ $response->assertSessionHas('success', 'Profile updated successfully.');
+
+ // Assert the user was updated in the database
+ $this->assertDatabaseHas('users', [
+ 'id' => $this->user->id,
+ 'name' => 'Updated Name',
+ 'email' => 'updated@example.com',
+ 'nik' => '654321',
+ ]);
+
+ // Refresh the user model from database
+ $this->user->refresh();
+
+ // Assert that the user has a sign value (any non-empty string)
+ $this->assertNotEmpty($this->user->sign);
+
+ // Debug information
+ $files = Storage::disk('public')->allFiles('signatures/' . $this->user->id);
+
+ // Assert the file has been stored in the expected location
+ // Use a more flexible check that doesn't rely on the exact filename
+ $signaturePath = 'signatures/' . $this->user->id;
+ $this->assertTrue(
+ Storage::disk('public')->exists($signaturePath . '/' . $this->user->sign),
+ "Signature file not found at expected location: {$signaturePath}/{$this->user->sign}"
+ );
+
+ // Verify old signature was deleted
+ Storage::disk('public')->assertMissing('signatures/' . $this->user->id . '/old-signature.jpg');
+ }
+}