user = User::factory()->create(); $this->token = $this->user->createToken('test-token')->plainTextToken; } public function test_calendar_slots_are_auto_created_when_trip_is_created() { $tripData = [ 'name' => 'Test Trip', 'description' => 'Test Description', 'start_date' => '2024-01-01', 'end_date' => '2024-01-03' ]; $response = $this->withHeaders([ 'Authorization' => 'Bearer ' . $this->token, 'Accept' => 'application/json' ])->postJson('/api/trips', $tripData); $response->assertStatus(201); $tripId = $response->json('data.id'); // Check that 3 calendar slots were created for this trip (Jan 1, 2, 3) $this->assertEquals(3, CalendarSlot::where('trip_id', $tripId)->count()); $slots = CalendarSlot::where('trip_id', $tripId) ->orderBy('slot_order') ->get(); $this->assertEquals('Day 1', $slots[0]->name); $this->assertEquals('2024-01-01', $slots[0]->slot_date->format('Y-m-d')); $this->assertEquals(1, $slots[0]->slot_order); $this->assertEquals('Day 2', $slots[1]->name); $this->assertEquals('2024-01-02', $slots[1]->slot_date->format('Y-m-d')); $this->assertEquals(2, $slots[1]->slot_order); $this->assertEquals('Day 3', $slots[2]->name); $this->assertEquals('2024-01-03', $slots[2]->slot_date->format('Y-m-d')); $this->assertEquals(3, $slots[2]->slot_order); } public function test_calendar_slots_are_updated_when_trip_dates_change() { $trip = Trip::factory()->create([ 'created_by_user_id' => $this->user->id, 'start_date' => '2024-01-01', 'end_date' => '2024-01-02' ]); // Initially should have 2 slots $this->assertCount(2, $trip->calendarSlots); // Update trip dates $response = $this->withHeaders([ 'Authorization' => 'Bearer ' . $this->token, 'Accept' => 'application/json' ])->putJson("/api/trips/{$trip->id}", [ 'name' => $trip->name, 'start_date' => '2024-02-01', 'end_date' => '2024-02-04' ]); $response->assertStatus(200); // Should now have 4 slots with new dates $trip->refresh(); $slots = $trip->calendarSlots()->orderBy('slot_order')->get(); $this->assertCount(4, $slots); $this->assertEquals('2024-02-01', $slots[0]->slot_date->format('Y-m-d')); $this->assertEquals('2024-02-02', $slots[1]->slot_date->format('Y-m-d')); $this->assertEquals('2024-02-03', $slots[2]->slot_date->format('Y-m-d')); $this->assertEquals('2024-02-04', $slots[3]->slot_date->format('Y-m-d')); } public function test_can_list_calendar_slots_for_trip() { $trip = Trip::factory()->create([ 'created_by_user_id' => $this->user->id, 'start_date' => '2024-01-01', 'end_date' => '2024-01-03' ]); $response = $this->withHeaders([ 'Authorization' => 'Bearer ' . $this->token, 'Accept' => 'application/json' ])->getJson("/api/trips/{$trip->id}/calendar-slots"); $response->assertStatus(200) ->assertJsonCount(3, 'data') ->assertJsonPath('data.0.name', 'Day 1') ->assertJsonPath('data.1.name', 'Day 2') ->assertJsonPath('data.2.name', 'Day 3'); } public function test_can_update_calendar_slot_name() { $trip = Trip::factory()->create([ 'created_by_user_id' => $this->user->id, 'start_date' => '2024-01-01', 'end_date' => '2024-01-01' ]); $slot = $trip->calendarSlots()->first(); $response = $this->withHeaders([ 'Authorization' => 'Bearer ' . $this->token, 'Accept' => 'application/json' ])->putJson("/api/calendar-slots/{$slot->id}", [ 'name' => 'Arrival Day' ]); $response->assertStatus(200) ->assertJsonPath('data.name', 'Arrival Day'); $this->assertDatabaseHas('calendar_slots', [ 'id' => $slot->id, 'name' => 'Arrival Day' ]); } public function test_cannot_access_calendar_slots_of_other_users_trip() { $otherUser = User::factory()->create(); $otherTrip = Trip::factory()->create([ 'created_by_user_id' => $otherUser->id, 'start_date' => '2024-01-01', 'end_date' => '2024-01-02' ]); $response = $this->withHeaders([ 'Authorization' => 'Bearer ' . $this->token, 'Accept' => 'application/json' ])->getJson("/api/trips/{$otherTrip->id}/calendar-slots"); $response->assertStatus(403); } public function test_cannot_update_calendar_slot_of_other_users_trip() { $otherUser = User::factory()->create(); $otherTrip = Trip::factory()->create([ 'created_by_user_id' => $otherUser->id, 'start_date' => '2024-01-01', 'end_date' => '2024-01-01' ]); $slot = $otherTrip->calendarSlots()->first(); $response = $this->withHeaders([ 'Authorization' => 'Bearer ' . $this->token, 'Accept' => 'application/json' ])->putJson("/api/calendar-slots/{$slot->id}", [ 'name' => 'Hacked Name' ]); $response->assertStatus(403); } public function test_no_slots_created_for_trip_without_dates() { $tripData = [ 'name' => 'Trip without dates', 'description' => 'No dates set' ]; $response = $this->withHeaders([ 'Authorization' => 'Bearer ' . $this->token, 'Accept' => 'application/json' ])->postJson('/api/trips', $tripData); $response->assertStatus(201); $tripId = $response->json('data.id'); // No slots should be created $this->assertDatabaseCount('calendar_slots', 0); $slots = CalendarSlot::where('trip_id', $tripId)->get(); $this->assertCount(0, $slots); } public function test_slots_created_when_dates_added_to_trip() { $trip = Trip::factory()->create([ 'created_by_user_id' => $this->user->id, 'start_date' => null, 'end_date' => null ]); // Initially no slots $this->assertCount(0, $trip->calendarSlots); // Add dates to trip $response = $this->withHeaders([ 'Authorization' => 'Bearer ' . $this->token, 'Accept' => 'application/json' ])->putJson("/api/trips/{$trip->id}", [ 'name' => $trip->name, 'start_date' => '2024-03-01', 'end_date' => '2024-03-02' ]); $response->assertStatus(200); // Now should have 2 slots $trip->refresh(); $this->assertCount(2, $trip->calendarSlots); } }