token = User::factory()->create()->createToken('test-token')->plainTextToken; }); test('lists active routes with nested company, destinations, time slots and pricing', function () { $route = EvRoute::factory()->create(['is_active' => true]); EvRoute::factory()->create(['is_active' => false]); $slot = DepartureTimeSlot::factory()->create(); $route->timeSlots()->attach($slot->id, ['is_active' => true]); RoutePricing::factory()->create([ 'ev_route_id' => $route->id, 'vehicle_option' => VehicleOption::FrontSeat, 'price' => 12000, ]); $this->withHeader('Authorization', "Bearer {$this->token}") ->getJson('/api/v1/routes') ->assertSuccessful() ->assertJsonCount(1, 'data') ->assertJsonPath('data.0.id', $route->id) ->assertJsonPath('data.0.company.id', $route->ev_company_id) ->assertJsonPath('data.0.from_destination.id', $route->from_destination_id) ->assertJsonPath('data.0.to_destination.id', $route->to_destination_id) ->assertJsonPath('data.0.time_slots.0.id', $slot->id) ->assertJsonPath('data.0.time_slots.0.is_active', true) ->assertJsonPath('data.0.pricing.0.vehicle_option', 'front_seat') ->assertJsonPath('data.0.pricing.0.price', '12000.00'); }); test('filters routes by company, from, and to', function () { $companyA = EvCompany::factory()->create(); $companyB = EvCompany::factory()->create(); $yangon = Destination::factory()->create(); $mandalay = Destination::factory()->create(); $bagan = Destination::factory()->create(); $matching = EvRoute::factory()->create([ 'ev_company_id' => $companyA->id, 'from_destination_id' => $yangon->id, 'to_destination_id' => $mandalay->id, 'is_active' => true, ]); EvRoute::factory()->create([ 'ev_company_id' => $companyB->id, 'from_destination_id' => $yangon->id, 'to_destination_id' => $mandalay->id, 'is_active' => true, ]); EvRoute::factory()->create([ 'ev_company_id' => $companyA->id, 'from_destination_id' => $yangon->id, 'to_destination_id' => $bagan->id, 'is_active' => true, ]); $this->withHeader('Authorization', "Bearer {$this->token}") ->getJson('/api/v1/routes?'.http_build_query([ 'company' => $companyA->id, 'from' => $yangon->id, 'to' => $mandalay->id, ])) ->assertSuccessful() ->assertJsonCount(1, 'data') ->assertJsonPath('data.0.id', $matching->id); }); test('shows a single active route', function () { $route = EvRoute::factory()->create(['is_active' => true]); $this->withHeader('Authorization', "Bearer {$this->token}") ->getJson("/api/v1/routes/{$route->id}") ->assertSuccessful() ->assertJsonPath('data.id', $route->id); }); test('an inactive route is not found via show, pricing, or time-slots', function () { $route = EvRoute::factory()->create(['is_active' => false]); $this->withHeader('Authorization', "Bearer {$this->token}") ->getJson("/api/v1/routes/{$route->id}") ->assertNotFound(); $this->withHeader('Authorization', "Bearer {$this->token}") ->getJson("/api/v1/routes/{$route->id}/pricing") ->assertNotFound(); $this->withHeader('Authorization', "Bearer {$this->token}") ->getJson("/api/v1/routes/{$route->id}/time-slots") ->assertNotFound(); }); test('lists a route\'s pricing including blocked options', function () { $route = EvRoute::factory()->create(['is_active' => true]); RoutePricing::factory()->create(['ev_route_id' => $route->id, 'vehicle_option' => VehicleOption::FrontSeat, 'price' => 12000]); RoutePricing::factory()->create(['ev_route_id' => $route->id, 'vehicle_option' => VehicleOption::WholeVehicle, 'is_blocked' => true]); $this->withHeader('Authorization', "Bearer {$this->token}") ->getJson("/api/v1/routes/{$route->id}/pricing") ->assertSuccessful() ->assertJsonCount(2, 'data') ->assertJsonFragment(['vehicle_option' => 'front_seat', 'price' => '12000.00', 'is_blocked' => false]) ->assertJsonFragment(['vehicle_option' => 'whole_vehicle', 'is_blocked' => true]); }); test('lists a route\'s time slots with the pivot active flag', function () { $route = EvRoute::factory()->create(['is_active' => true]); $active = DepartureTimeSlot::factory()->create(); $inactive = DepartureTimeSlot::factory()->create(); $route->timeSlots()->attach([ $active->id => ['is_active' => true], $inactive->id => ['is_active' => false], ]); $this->withHeader('Authorization', "Bearer {$this->token}") ->getJson("/api/v1/routes/{$route->id}/time-slots") ->assertSuccessful() ->assertJsonCount(2, 'data') ->assertJsonFragment(['id' => $active->id, 'is_active' => true]) ->assertJsonFragment(['id' => $inactive->id, 'is_active' => false]); }); test('routes endpoints reject unauthenticated requests', function () { $route = EvRoute::factory()->create(['is_active' => true]); $this->getJson('/api/v1/routes')->assertUnauthorized(); $this->getJson("/api/v1/routes/{$route->id}")->assertUnauthorized(); $this->getJson("/api/v1/routes/{$route->id}/pricing")->assertUnauthorized(); $this->getJson("/api/v1/routes/{$route->id}/time-slots")->assertUnauthorized(); });