user = User::factory() ->active() ->has(Employee::factory()) ->create(); }); function mountCreateComponent(User $user): Testable { return Livewire::actingAs($user)->test(Create::class); } it('renders page successfully', function () { mountCreateComponent($this->user) ->assertViewIs('livewire.studio.master.user.form') ->assertViewHas('pageTitle', 'Tambah Pegawai'); }); it('loads outlets and roles on mount', function () { $outlet = Outlet::factory()->create(); $role = Role::create(['name' => 'Admin']); $component = mountCreateComponent($this->user); expect($component->outlets)->toBeArray(); expect($component->outlets)->toHaveKey($outlet->id); expect($component->roles)->toBeArray(); expect($component->roles)->toHaveKey($role->id); }); it('excludes developer role from roles list', function () { Role::create(['name' => 'Developer']); $adminRole = Role::create(['name' => 'Admin']); $component = mountCreateComponent($this->user); expect($component->roles)->not->toHaveKey(Role::where('name', 'Developer')->first()->id); expect($component->roles)->toHaveKey($adminRole->id); }); it('prevents create when user is unauthorized', function () { Gate::define('create user', fn () => false); mountCreateComponent($this->user) ->call('save') ->assertForbidden(); }); it('creates user successfully when authorized', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $outlet = Outlet::factory()->create(); $role = Role::create(['name' => 'Admin']); $defaultPassword = config('myconfig.password_default'); mountCreateComponent($this->user) ->set('form.full_name', 'John Doe') ->set('form.username', 'johndoe') ->set('form.email', 'john@example.com') ->set('form.phone_number', '0812 3456 7890') ->set('form.base_salary', '5000000') ->set('form.birthdate', now()->subYears(25)->format('Y-m-d')) ->set('form.hire_date', now()->subMonths(6)->format('Y-m-d')) ->set('form.gender', Gender::MALE->value) ->set('form.status', UserStatus::ACTIVE->value) ->set('form.outlet_ids', [$outlet->id]) ->set('form.role_ids', [$role->id]) ->call('save') ->assertHasNoErrors() ->assertRedirect(Index::class); $createdUser = User::where('email', 'john@example.com')->first(); expect($createdUser)->not->toBeNull() ->and($createdUser->username)->toBe('johndoe') ->and($createdUser->status)->toBe(UserStatus::ACTIVE) ->and(Hash::check($defaultPassword, $createdUser->password))->toBeTrue(); $this->assertDatabaseHas('employees', [ 'user_id' => $createdUser->id, 'full_name' => 'John Doe', 'gender' => Gender::MALE, ]); expect($createdUser->outlets)->toHaveCount(1) ->and($createdUser->roles)->toHaveCount(1) ->and($createdUser->referralCode)->not->toBeNull(); }); it('creates user with inactive status and sets resign date', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $outlet = Outlet::factory()->create(); $role = Role::create(['name' => 'Admin']); $birthdate = now()->subYears(25)->format('Y-m-d'); $hireDate = now()->subMonths(6)->format('Y-m-d'); mountCreateComponent($this->user) ->set('form.full_name', 'Jane Doe') ->set('form.username', 'janedoe') ->set('form.email', 'jane@example.com') ->set('form.phone_number', '0812 3456 7891') ->set('form.base_salary', '4.500.000') ->set('form.birthdate', $birthdate) ->set('form.hire_date', $hireDate) ->set('form.gender', Gender::FEMALE->value) ->set('form.status', UserStatus::INACTIVE->value) ->set('form.outlet_ids', [$outlet->id]) ->set('form.role_ids', [$role->id]) ->call('save') ->assertHasNoErrors(); $createdUser = User::where('email', 'jane@example.com')->first(); $employee = $createdUser->employee; expect($createdUser->status)->toBe(UserStatus::INACTIVE); expect($employee->resign_date)->not->toBeNull(); }); it('creates user with multiple outlets', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $outlet1 = Outlet::factory()->create(); $outlet2 = Outlet::factory()->create(); $outlet3 = Outlet::factory()->create(); $role = Role::create(['name' => 'Admin']); $birthdate = now()->subYears(25)->format('Y-m-d'); $hireDate = now()->subMonths(6)->format('Y-m-d'); mountCreateComponent($this->user) ->set('form.full_name', 'Multiple Outlet User') ->set('form.username', 'multioutlet') ->set('form.email', 'multi@example.com') ->set('form.phone_number', '0812 3456 7892') ->set('form.base_salary', '5.500.000') ->set('form.birthdate', $birthdate) ->set('form.hire_date', $hireDate) ->set('form.gender', Gender::MALE->value) ->set('form.status', UserStatus::ACTIVE->value) ->set('form.outlet_ids', [$outlet1->id, $outlet2->id, $outlet3->id]) ->set('form.role_ids', [$role->id]) ->call('save') ->assertHasNoErrors(); $createdUser = User::where('email', 'multi@example.com')->first(); expect($createdUser->outlets->count())->toBe(3); expect($createdUser->outlets->pluck('id')->toArray())->toContain($outlet1->id, $outlet2->id, $outlet3->id); }); it('creates user with multiple roles', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $outlet = Outlet::factory()->create(); $adminRole = Role::create(['name' => 'Admin']); $leaderRole = Role::create(['name' => 'Leader']); $birthdate = now()->subYears(25)->format('Y-m-d'); $hireDate = now()->subMonths(6)->format('Y-m-d'); mountCreateComponent($this->user) ->set('form.full_name', 'Multiple Role User') ->set('form.username', 'multirole') ->set('form.email', 'role@example.com') ->set('form.phone_number', '0812 3456 7893') ->set('form.base_salary', '6.000.000') ->set('form.birthdate', $birthdate) ->set('form.hire_date', $hireDate) ->set('form.gender', Gender::MALE->value) ->set('form.status', UserStatus::ACTIVE->value) ->set('form.outlet_ids', [$outlet->id]) ->set('form.role_ids', [$adminRole->id, $leaderRole->id]) ->call('save') ->assertHasNoErrors(); $createdUser = User::where('email', 'role@example.com')->first(); expect($createdUser->roles->count())->toBe(2); expect($createdUser->roles->pluck('id')->toArray())->toContain($adminRole->id, $leaderRole->id); }); it('validates required fields', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $component = mountCreateComponent($this->user); // Don't set any required fields to ensure they're validated $component->call('save') ->assertHasErrors([ 'form.full_name', 'form.username', 'form.email', 'form.phone_number', 'form.base_salary', 'form.birthdate', 'form.hire_date', 'form.gender', 'form.outlet_ids', 'form.role_ids', ]); }); it('validates full_name field max length', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.full_name', str_repeat('a', 101)) ->call('save') ->assertHasErrors(['form.full_name']); }); it('validates username field required', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.full_name', 'Test User') ->call('save') ->assertHasErrors(['form.username']); }); it('validates username field alpha numeric', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.username', 'test-user@123') ->call('save') ->assertHasErrors(['form.username']); }); it('validates username field min length', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.username', 'test') ->call('save') ->assertHasErrors(['form.username']); }); it('validates username field max length', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.username', str_repeat('a', 21)) ->call('save') ->assertHasErrors(['form.username']); }); it('validates username field uniqueness', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $existingUser = User::factory()->create(['username' => 'existinguser']); mountCreateComponent($this->user) ->set('form.username', 'existinguser') ->call('save') ->assertHasErrors(['form.username']); }); it('validates email field required', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.full_name', 'Test User') ->set('form.username', 'testuser') ->call('save') ->assertHasErrors(['form.email']); }); it('validates email field format', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.email', 'invalid-email') ->call('save') ->assertHasErrors(['form.email']); }); it('validates email field max length', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.email', str_repeat('a', 90).'@example.com') ->call('save') ->assertHasErrors(['form.email']); }); it('validates email field uniqueness', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $existingUser = User::factory()->create(['email' => 'existing@example.com']); mountCreateComponent($this->user) ->set('form.email', 'existing@example.com') ->call('save') ->assertHasErrors(['form.email']); }); it('validates phone_number field required', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.full_name', 'Test User') ->set('form.username', 'testuser') ->set('form.email', 'test@example.com') ->call('save') ->assertHasErrors(['form.phone_number']); }); it('validates base_salary field required', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.full_name', 'Test User') ->set('form.username', 'testuser') ->set('form.email', 'test@example.com') ->call('save') ->assertHasErrors(['form.base_salary']); }); it('validates birthdate field required', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.full_name', 'Test User') ->set('form.username', 'testuser') ->set('form.email', 'test@example.com') ->call('save') ->assertHasErrors(['form.birthdate']); }); it('validates birthdate must be before 18 years ago', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $birthdate = now()->subYears(17)->format('Y-m-d'); mountCreateComponent($this->user) ->set('form.birthdate', $birthdate) ->call('save') ->assertHasErrors(['form.birthdate']); }); it('validates hire_date field required', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.full_name', 'Test User') ->set('form.username', 'testuser') ->set('form.email', 'test@example.com') ->call('save') ->assertHasErrors(['form.hire_date']); }); it('validates gender field required', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.full_name', 'Test User') ->set('form.username', 'testuser') ->set('form.email', 'test@example.com') ->call('save') ->assertHasErrors(['form.gender']); }); it('validates gender field must be valid enum value', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.gender', 999) // Invalid enum value ->call('save') ->assertHasErrors(['form.gender']); }); it('validates status field required', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.full_name', 'Test User') ->set('form.username', 'testuser') ->set('form.email', 'test@example.com') ->set('form.status', 99) // Invalid enum value ->call('save') ->assertHasErrors(['form.status']); }); it('validates status field must be valid enum value', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.status', '99') ->call('save') ->assertHasErrors(['form.status']); }); it('validates outlet_ids field required', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.full_name', 'Test User') ->set('form.username', 'testuser') ->set('form.email', 'test@example.com') ->call('save') ->assertHasErrors(['form.outlet_ids']); }); it('validates outlet_ids must be array', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $this->expectException(TypeError::class); mountCreateComponent($this->user) ->set('form.outlet_ids', 'not-array') ->call('save') ->assertHasErrors(['form.outlet_ids']); }); it('validates outlet_ids minimum count', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.outlet_ids', []) ->call('save') ->assertHasErrors(['form.outlet_ids']); }); it('validates outlet_ids must exist', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.outlet_ids', [99999]) ->call('save') ->assertHasErrors(['form.outlet_ids.0']); }); it('validates role_ids field required', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.full_name', 'Test User') ->set('form.username', 'testuser') ->set('form.email', 'test@example.com') ->call('save') ->assertHasErrors(['form.role_ids']); }); it('validates role_ids must be array', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $this->expectException(TypeError::class); mountCreateComponent($this->user) ->set('form.role_ids', 'not-array') ->call('save') ->assertHasErrors(['form.role_ids']); }); it('validates role_ids minimum count', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.role_ids', []) ->call('save') ->assertHasErrors(['form.role_ids']); }); it('validates role_ids must exist', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); mountCreateComponent($this->user) ->set('form.role_ids', [99999]) ->call('save') ->assertHasErrors(['form.role_ids.0']); }); it('creates employee code automatically', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $outlet = Outlet::factory()->create(); $role = Role::create(['name' => 'Admin']); $birthdate = now()->subYears(25)->format('Y-m-d'); $hireDate = now()->subMonths(6)->format('Y-m-d'); mountCreateComponent($this->user) ->set('form.full_name', 'Employee Code Test') ->set('form.username', 'empcodetest') ->set('form.email', 'empcode@example.com') ->set('form.phone_number', '0812 3456 7894') ->set('form.base_salary', '4.000.000') ->set('form.birthdate', $birthdate) ->set('form.hire_date', $hireDate) ->set('form.gender', Gender::MALE->value) ->set('form.status', UserStatus::ACTIVE->value) ->set('form.outlet_ids', [$outlet->id]) ->set('form.role_ids', [$role->id]) ->call('save') ->assertHasNoErrors(); $createdUser = User::where('email', 'empcode@example.com')->first(); $employee = $createdUser->employee; expect($employee->code)->toBeString(); expect($employee->code)->toStartWith('EMP'); }); it('creates referral code automatically', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $outlet = Outlet::factory()->create(); $role = Role::create(['name' => 'Admin']); $birthdate = now()->subYears(25)->format('Y-m-d'); $hireDate = now()->subMonths(6)->format('Y-m-d'); mountCreateComponent($this->user) ->set('form.full_name', 'Referral Code Test') ->set('form.username', 'refcodetest') ->set('form.email', 'refcode@example.com') ->set('form.phone_number', '0812 3456 7895') ->set('form.base_salary', '4.500.000') ->set('form.birthdate', $birthdate) ->set('form.hire_date', $hireDate) ->set('form.gender', Gender::MALE->value) ->set('form.status', UserStatus::ACTIVE->value) ->set('form.outlet_ids', [$outlet->id]) ->set('form.role_ids', [$role->id]) ->call('save') ->assertHasNoErrors(); $createdUser = User::where('email', 'refcode@example.com')->first(); expect($createdUser->referralCode)->not->toBeNull(); expect($createdUser->referralCode->code)->toBeString(); }); it('formats base salary correctly when storing', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $outlet = Outlet::factory()->create(); $role = Role::create(['name' => 'Admin']); $birthdate = now()->subYears(25)->format('Y-m-d'); $hireDate = now()->subMonths(6)->format('Y-m-d'); mountCreateComponent($this->user) ->set('form.full_name', 'Salary Format Test') ->set('form.username', 'salarytest') ->set('form.email', 'salary@example.com') ->set('form.phone_number', '0812 3456 7896') ->set('form.base_salary', '5.500.000') ->set('form.birthdate', $birthdate) ->set('form.hire_date', $hireDate) ->set('form.gender', Gender::MALE->value) ->set('form.status', UserStatus::ACTIVE->value) ->set('form.outlet_ids', [$outlet->id]) ->set('form.role_ids', [$role->id]) ->call('save') ->assertHasNoErrors(); $createdUser = User::where('email', 'salary@example.com')->first(); $employee = $createdUser->employee; expect($employee->base_salary)->toBe(5500000); }); it('allows nullable address field', function () { $permission = Permission::create(['name' => 'create user']); $this->user->givePermissionTo($permission); $outlet = Outlet::factory()->create(); $role = Role::create(['name' => 'Admin']); $birthdate = now()->subYears(25)->format('Y-m-d'); $hireDate = now()->subMonths(6)->format('Y-m-d'); mountCreateComponent($this->user) ->set('form.full_name', 'No Address Test') ->set('form.username', 'noaddresstest') ->set('form.email', 'noaddress@example.com') ->set('form.phone_number', '0812 3456 7897') ->set('form.base_salary', '4.000.000') ->set('form.birthdate', $birthdate) ->set('form.hire_date', $hireDate) ->set('form.address', null) ->set('form.gender', Gender::MALE->value) ->set('form.status', UserStatus::ACTIVE->value) ->set('form.outlet_ids', [$outlet->id]) ->set('form.role_ids', [$role->id]) ->call('save') ->assertHasNoErrors(); $createdUser = User::where('email', 'noaddress@example.com')->first(); $employee = $createdUser->employee; expect($employee->address)->toBeNull(); });