239 lines
7.4 KiB
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);
|
|
}
|
|
}
|