'testuser@example.com'], [ 'name' => 'Test Employee', 'password' => bcrypt('password'), 'is_enable_login' => 1, 'status' => 'active', 'slug' => 'test-employee', ] ); $branch = \App\Models\Branch::firstOrCreate( ['id' => 1], ['name' => 'Main HQ Branch', 'created_by' => $user->id, 'status' => 'active'] ); $shift = \App\Models\Shift::firstOrCreate( ['name' => 'Day Shift'], [ 'start_time' => '08:00:00', 'end_time' => '17:00:00', 'status' => 'active', 'created_by' => $user->id, ] ); updateSetting('working_days', json_encode([0,1,2,3,4,5,6])); $employee = Employee::firstOrCreate( ['user_id' => $user->id], [ 'name' => 'Test Employee', 'email' => 'testuser@example.com', 'employee_id' => 'EMP-TEST-001', 'branch_id' => $branch->id, 'shift_id' => $shift->id, 'created_by' => $user->id, ] ); return $user; } public function test_login_issues_valid_sanctum_token() { $user = $this->getTestUser(); $response = $this->postJson('/api/auth/login', [ 'email' => 'testuser@example.com', 'password' => 'password', ]); $response->assertStatus(200) ->assertJsonStructure(['success', 'token', 'user']); } public function test_unauthenticated_request_returns_401() { $response = $this->getJson('/api/user'); $response->assertStatus(401); } public function test_server_time_is_public() { $response = $this->getJson('/api/server-time'); $response->assertStatus(200) ->assertJson(['success' => true]); } public function test_attendance_clock_in_and_clock_out_workflow() { $user = $this->getTestUser(); $token = $user->createToken('test')->plainTextToken; // Clock In $clockInResponse = $this->withHeaders(['Authorization' => "Bearer {$token}"]) ->postJson('/api/attendance/clock', [ 'action' => 'clock_in', 'latitude' => 14.5995, 'longitude' => 120.9842, 'notes' => 'Test arrival', ]); $clockInResponse->assertStatus(200) ->assertJson(['success' => true]); // Assert Database storage after Clock In $this->assertDatabaseHas('attendance_records', [ 'employee_id' => $user->id, 'clock_in_source' => 'mobile', ]); // Assert /attendance/today returns clocked_in: true $todayResponse = $this->withHeaders(['Authorization' => "Bearer {$token}"]) ->getJson('/api/attendance/today'); $todayResponse->assertStatus(200) ->assertJson([ 'success' => true, 'data' => [ 'clocked_in' => true, ] ]); // Clock Out $clockOutResponse = $this->withHeaders(['Authorization' => "Bearer {$token}"]) ->postJson('/api/attendance/clock', [ 'action' => 'clock_out', 'latitude' => 14.5995, 'longitude' => 120.9842, 'notes' => 'Test departure', ]); $clockOutResponse->assertStatus(200) ->assertJson(['success' => true]); // Assert Database storage after Clock Out $this->assertDatabaseHas('attendance_records', [ 'employee_id' => $user->id, 'clock_out_source' => 'mobile', ]); } public function test_clock_out_without_clock_in_fails_with_422() { $user = User::create([ 'name' => 'No Clockin User', 'email' => 'noclockin@example.com', 'password' => bcrypt('password'), 'is_enable_login' => 1, 'status' => 'active', 'slug' => 'no-clockin-user', ]); Employee::create([ 'user_id' => $user->id, 'name' => 'No Clockin User', 'email' => 'noclockin@example.com', 'employee_id' => 'EMP-NOCLOCKIN-002', 'created_by' => $user->id, ]); $token = $user->createToken('test')->plainTextToken; $response = $this->withHeaders(['Authorization' => "Bearer {$token}"]) ->postJson('/api/attendance/clock', [ 'action' => 'clock_out', ]); $response->assertStatus(422) ->assertJson(['success' => false]); } public function test_leave_application_submission() { $user = $this->getTestUser(); $token = $user->createToken('test')->plainTextToken; $response = $this->withHeaders(['Authorization' => "Bearer {$token}"]) ->postJson('/api/leaves/apply', [ 'leave_type' => 'vacation', 'start_date' => date('Y-m-d', strtotime('+5 days')), 'end_date' => date('Y-m-d', strtotime('+7 days')), 'reason' => 'Vacation Leave Test', ]); $response->assertStatus(201) ->assertJson(['success' => true]); } public function test_reimbursement_claim_creation() { $user = $this->getTestUser(); $token = $user->createToken('test')->plainTextToken; $response = $this->withHeaders(['Authorization' => "Bearer {$token}"]) ->postJson('/api/reimbursements', [ 'item_name' => 'Client Meal', 'amount' => 1250.00, 'category' => 'Meals', 'purchase_date' => date('Y-m-d'), 'notes' => 'Dinner with client', ]); $response->assertStatus(201) ->assertJson(['success' => true]); } public function test_mobile_task_crud() { $user = $this->getTestUser(); $token = $user->createToken('test')->plainTextToken; // Create Task $createRes = $this->withHeaders(['Authorization' => "Bearer {$token}"]) ->postJson('/api/tasks', [ 'title' => 'Feature Test Task', 'description' => 'Testing task creation', 'priority' => 'high', ]); $createRes->assertStatus(201) ->assertJson(['success' => true]); $taskId = $createRes->json('data.id'); // Pin Task $pinRes = $this->withHeaders(['Authorization' => "Bearer {$token}"]) ->postJson("/api/tasks/{$taskId}/pin"); $pinRes->assertStatus(200); // Status Update $statusRes = $this->withHeaders(['Authorization' => "Bearer {$token}"]) ->postJson("/api/tasks/{$taskId}/status", ['status' => 'done']); $statusRes->assertStatus(200); } }