Files
HRM-System/tests/Feature/Api/MobileBackendApiTest.php

239 lines
7.4 KiB
PHP

<?php
namespace Tests\Feature\Api;
use App\Models\User;
use App\Models\Employee;
use App\Models\AttendanceRecord;
use App\Models\LeaveApplication;
use App\Models\TripExpense;
use Tests\TestCase;
use Illuminate\Support\Facades\Artisan;
class MobileBackendApiTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
Artisan::call('migrate');
}
private function getTestUser()
{
$user = User::firstOrCreate(
['email' => '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);
}
}