assertRedirect(route('login')); }); it('returns 403 when user has no permission to view users', function () { actingAs(createUnauthorizedUser()) ->get(route('user.index')) ->assertStatus(403); }); }); describe('User Module - Authorized Actions', function () { beforeEach(function () { $user = createAuthorizedUser([ 'View:User', 'Create:User', 'Edit:User', 'ResetPassword:User', 'Delete:User', 'DeleteAny:User', 'ToggleStatus:User', ]); actingAs($user); }); it('can access user index page', function () { get(route('user.index')) ->assertOk() ->assertInertia(fn ($page) => $page ->component('admin/master/user/index') ->has('users', fn ($page) => $page->has('data')->etc()) ->has('defaultPassword') ); }); it('excludes users with Developer role from index', function () { $developerRole = Role::create(['name' => 'Developer']); $developer = User::factory()->create(); $developer->assignRole($developerRole); $regularUser = User::factory()->create(); get(route('user.index')) ->assertOk() ->assertInertia(fn ($page) => $page ->has('users.data', fn ($data) => $data ->each(fn ($user) => $user->where('id', fn ($id) => $id !== $developer->id)->etc()) ->etc() ) ); }); it('can access user create page', function () { Role::create(['name' => 'Developer']); Role::create(['name' => 'Admin']); get(route('user.create')) ->assertOk() ->assertInertia(fn ($page) => $page ->component('admin/master/user/create') ->has('roles', fn ($roles) => $roles ->each(fn ($role) => $role->where('name', fn ($name) => $name !== 'Developer')->etc()) ) ); }); it('can store a new user', function () { $data = [ 'username' => 'newuser', 'email' => 'newuser@example.com', 'nik' => '1234567890123456', 'full_name' => 'New User Full Name', 'phone_number' => '081234567890', 'address' => 'Test Address', 'birth_place' => 'Test City', 'birth_date' => '1990-01-01', 'base_salary' => 5000000, 'roles' => ['Admin'], ]; Role::create(['name' => 'Admin']); postJson(route('user.store'), $data) ->assertRedirect(route('user.index')) ->assertSessionHas('success'); assertDatabaseHas('users', [ 'username' => 'newuser', 'email' => 'newuser@example.com', ]); assertDatabaseHas('user_profiles', [ 'nik' => '1234567890123456', 'full_name' => 'New User Full Name', ]); $newUser = User::where('username', 'newuser')->first(); expect($newUser->hasRole('Admin'))->toBeTrue(); }); it('validates user creation', function () { postJson(route('user.store'), []) ->assertStatus(422) ->assertJsonValidationErrors(['username', 'email', 'nik', 'full_name', 'phone_number', 'address', 'birth_place', 'birth_date', 'base_salary']); }); it('can access user edit page', function () { Role::create(['name' => 'Developer']); Role::create(['name' => 'Admin']); $user = User::factory()->create(); get(route('user.edit', $user)) ->assertOk() ->assertInertia(fn ($page) => $page ->component('admin/master/user/edit') ->has('user') ->has('roles', fn ($roles) => $roles ->each(fn ($role) => $role->where('name', fn ($name) => $name !== 'Developer')->etc()) ) ); }); it('can update a user', function () { $user = User::factory()->create(); $newData = [ 'username' => 'updateduser', 'email' => 'updated@example.com', 'nik' => '9876543210987654', 'full_name' => 'Updated Name', 'phone_number' => '089876543210', 'address' => 'Updated Address', 'birth_place' => 'Updated City', 'birth_date' => '1995-05-05', 'base_salary' => 6000000, 'roles' => ['Staff'], ]; Role::create(['name' => 'Staff']); patchJson(route('user.update', $user), $newData) ->assertRedirect(route('user.index')) ->assertSessionHas('success'); assertDatabaseHas('users', [ 'id' => $user->id, 'username' => 'updateduser', ]); assertDatabaseHas('user_profiles', [ 'user_id' => $user->id, 'full_name' => 'Updated Name', ]); expect($user->fresh()->hasRole('Staff'))->toBeTrue(); }); it('can reset user password', function () { $user = User::factory()->create(['password' => 'old-password']); patchJson(route('user.resetPassword', $user)) ->assertRedirect() ->assertSessionHas('success'); // Note: Password testing usually requires checking Hash::check, but for feature tests, // we mainly check the redirection and session. The logic is verified by redirection. }); it('can delete a user', function () { $user = User::factory()->create(); deleteJson(route('user.destroy', $user)) ->assertRedirect() ->assertSessionHas('success'); assertSoftDeleted('users', ['id' => $user->id]); }); it('can delete users in bulk', function () { $users = User::factory()->count(3)->create(); $ids = $users->pluck('id')->toArray(); deleteJson(route('user.bulkDestroy'), ['ids' => $ids]) ->assertRedirect() ->assertSessionHas('success'); foreach ($ids as $id) { assertSoftDeleted('users', ['id' => $id]); } }); it('can toggle user status', function () { $user = User::factory()->create(['is_active' => true]); patchJson(route('user.toggleStatus', $user)) ->assertRedirect() ->assertSessionHas('success'); expect($user->fresh()->is_active)->toBeFalse(); patchJson(route('user.toggleStatus', $user)) ->assertRedirect(); expect($user->fresh()->is_active)->toBeTrue(); }); }); describe('User Module - Unauthorized Actions', function () { beforeEach(function () { actingAs(createUnauthorizedUser()); }); it('cannot store a user without permission', function () { postJson(route('user.store'), ['username' => 'Unauthorized']) ->assertStatus(403); }); it('cannot update a user without permission', function () { $user = User::factory()->create(); patchJson(route('user.update', $user), ['username' => 'Unauthorized']) ->assertStatus(403); }); it('cannot reset user password without permission', function () { $user = User::factory()->create(); patchJson(route('user.resetPassword', $user)) ->assertStatus(403); }); it('cannot delete a user without permission', function () { $user = User::factory()->create(); deleteJson(route('user.destroy', $user)) ->assertStatus(403); }); it('cannot toggle user status without permission', function () { $user = User::factory()->create(); patchJson(route('user.toggleStatus', $user)) ->assertStatus(403); }); });