Files
Verde-Web/tests/Feature/Api/V1/Trip/E2EWasteCollectionTest.php

155 lines
5.6 KiB
PHP

<?php
namespace Tests\Feature\Api\V1\Trip;
use App\Models\CollectionTeam;
use App\Models\DropOffPoint;
use App\Models\Dumpsite;
use App\Models\QrCode;
use App\Models\Route;
use App\Models\Trip;
use App\Models\User;
use Database\Seeders\RoleSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class E2EWasteCollectionTest extends TestCase
{
use RefreshDatabase;
public function test_full_waste_collection_lifecycle_end_to_end()
{
// 1. Setup Environment & Test Data
$this->seed([
RoleSeeder::class,
\Database\Seeders\SamplePsgcSeeder::class,
\Database\Seeders\SampleDropOffPointsSeeder::class,
\Database\Seeders\SampleDumpsitesSeeder::class,
]);
$admin = User::factory()->create(['role' => User::ROLE_ADMIN, 'status' => 'active']);
$driver = User::factory()->create(['role' => User::ROLE_DRIVER, 'status' => 'active']);
$scanner = User::factory()->create(['role' => User::ROLE_SCANNER, 'status' => 'active']);
$dumpsite = Dumpsite::first();
$dropOffPoint = DropOffPoint::first();
$route = Route::create([
'name' => 'E2E Test Route',
'code' => 'RT-E2E',
'default_dumpsite_id' => $dumpsite->id,
'status' => 'active',
]);
$route->stops()->create([
'drop_off_point_id' => $dropOffPoint->id,
'sequence' => 1,
]);
$team = CollectionTeam::create([
'name' => 'E2E Team',
'driver_id' => $driver->id,
'scanner_id' => $scanner->id,
'status' => 'active',
]);
// Set up a Resident QR Code
$resident = User::factory()->create(['role' => User::ROLE_RESIDENT, 'status' => 'active']);
$batch = \App\Models\QrCodeBatch::create([
'batch_number' => 'BATCH-E2E-1',
'status' => 'active',
'quantity' => 10,
]);
$qr = QrCode::create([
'serial' => 'E2E-TEST-QR-001',
'assigned_to_user_id' => $resident->id,
'batch_id' => $batch->id,
'status' => 'active',
]);
// ==========================================
// 2. Admin Schedules a Trip
// ==========================================
$response = $this->actingAs($admin)->postJson('/api/v1/admin/trips', [
'route_id' => $route->id,
'team_id' => $team->id,
'scheduled_date' => now()->toDateString(),
]);
$response->assertStatus(201);
$tripUuid = $response->json('data.id');
$this->assertNotNull($tripUuid);
$trip = Trip::where('uuid', $tripUuid)->first();
$this->assertEquals(Trip::STATUS_SCHEDULED, $trip->status);
// ==========================================
// 3. Driver Starts the Trip
// ==========================================
$response = $this->actingAs($driver)->postJson("/api/v1/driver/trips/{$tripUuid}/start");
$response->assertStatus(200);
$trip->refresh();
$this->assertEquals(Trip::STATUS_IN_PROGRESS, $trip->status);
// Driver arrives at the first stop
$stop = $trip->stops()->first();
$response = $this->actingAs($driver)->postJson("/api/v1/driver/trips/{$tripUuid}/stops/{$stop->id}/arrive", [
'lat' => $dropOffPoint->coordinates->latitude,
'lng' => $dropOffPoint->coordinates->longitude,
]);
$response->assertStatus(200);
// ==========================================
// 4. Scanner Scans a Household QR Code
// ==========================================
$response = $this->actingAs($scanner)->postJson('/api/v1/scanner/scan', [
'serial' => $qr->serial,
'drop_off_point_id' => $dropOffPoint->id,
'lat' => $dropOffPoint->coordinates->latitude,
'lng' => $dropOffPoint->coordinates->longitude,
'trip_id' => $tripUuid,
'trip_stop_id' => $stop->id,
'weight_kg' => 5,
]);
$response->assertStatus(200);
// Driver departs from the stop
$response = $this->actingAs($driver)->postJson("/api/v1/driver/trips/{$tripUuid}/stops/{$stop->id}/depart", [
'lat' => $dropOffPoint->coordinates->latitude,
'lng' => $dropOffPoint->coordinates->longitude,
]);
$response->assertStatus(200);
// ==========================================
// 5. Driver Arrives at Dumpsite and Completes
// ==========================================
$response = $this->actingAs($driver)->postJson("/api/v1/driver/trips/{$tripUuid}/arrive-dumpsite", [
'lat' => 14.1,
'lng' => 121.1,
'dumpsite_id' => $dumpsite->id,
'override_geofence' => true,
]);
$response->assertStatus(200);
$response = $this->actingAs($driver)->postJson("/api/v1/driver/trips/{$tripUuid}/release-load", [
'dumpsite_id' => $dumpsite->id,
'weight_kg' => 1000,
'override_geofence' => true,
]);
$response->assertStatus(201);
$response = $this->actingAs($driver)->postJson("/api/v1/driver/trips/{$tripUuid}/complete", [
'lat' => 14.1,
'lng' => 121.1,
'override_geofence' => true,
]);
$response->assertStatus(200);
// Verify Final State
$trip->refresh();
$this->assertEquals(Trip::STATUS_COMPLETED, $trip->status);
$this->assertEquals(1000, $trip->total_load_kg);
}
}