trip-planner/backend/tests/Feature/PlannableItemTest.php

188 lines
5.6 KiB
PHP
Raw Normal View History

<?php
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\User;
use App\Models\Trip;
use App\Models\PlannableItem;
use App\Models\CalendarSlot;
use Illuminate\Foundation\Testing\RefreshDatabase;
class PlannableItemTest extends TestCase
{
use RefreshDatabase;
private $user;
private $trip;
private $token;
protected function setUp(): void
{
parent::setUp();
$this->user = User::factory()->create();
$this->trip = Trip::factory()->create([
'created_by_user_id' => $this->user->id,
'start_date' => '2024-01-01',
'end_date' => '2024-01-03'
]);
$this->token = $this->user->createToken('test-token')->plainTextToken;
}
public function test_can_create_plannable_item()
{
$data = [
'name' => 'Eiffel Tower',
'type' => 'attraction',
'address' => 'Champ de Mars, Paris',
'notes' => 'Visit in the morning',
'metadata' => [
'opening_hours' => '9:00 AM - 11:00 PM',
'ticket_price' => '25 EUR'
]
];
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
'Accept' => 'application/json'
])->postJson("/api/trips/{$this->trip->id}/plannables", $data);
$response->assertStatus(201)
->assertJsonPath('data.name', 'Eiffel Tower')
->assertJsonPath('data.type', 'attraction')
->assertJsonPath('data.address', 'Champ de Mars, Paris')
->assertJsonPath('data.metadata.opening_hours', '9:00 AM - 11:00 PM');
$this->assertDatabaseHas('plannable_items', [
'trip_id' => $this->trip->id,
'name' => 'Eiffel Tower',
'type' => 'attraction'
]);
}
public function test_can_list_plannable_items_for_trip()
{
PlannableItem::factory()->count(3)->create([
'trip_id' => $this->trip->id
]);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
'Accept' => 'application/json'
])->getJson("/api/trips/{$this->trip->id}/plannables");
$response->assertStatus(200)
->assertJsonCount(3, 'data');
}
public function test_can_update_plannable_item()
{
$item = PlannableItem::factory()->create([
'trip_id' => $this->trip->id,
'name' => 'Old Name'
]);
$updateData = [
'name' => 'Updated Name',
'type' => 'restaurant',
'notes' => 'Updated notes'
];
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
'Accept' => 'application/json'
])->putJson("/api/plannables/{$item->id}", $updateData);
$response->assertStatus(200)
->assertJsonPath('data.name', 'Updated Name')
->assertJsonPath('data.type', 'restaurant');
$this->assertDatabaseHas('plannable_items', [
'id' => $item->id,
'name' => 'Updated Name',
'type' => 'restaurant'
]);
}
public function test_can_delete_plannable_item()
{
$item = PlannableItem::factory()->create([
'trip_id' => $this->trip->id
]);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
'Accept' => 'application/json'
])->deleteJson("/api/plannables/{$item->id}");
$response->assertStatus(204);
$this->assertDatabaseMissing('plannable_items', [
'id' => $item->id
]);
}
public function test_cannot_access_plannable_items_of_other_users_trip()
{
$otherUser = User::factory()->create();
$otherTrip = Trip::factory()->create([
'created_by_user_id' => $otherUser->id
]);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
'Accept' => 'application/json'
])->getJson("/api/trips/{$otherTrip->id}/plannables");
$response->assertStatus(403);
}
public function test_cannot_update_plannable_item_of_other_users_trip()
{
$otherUser = User::factory()->create();
$otherTrip = Trip::factory()->create([
'created_by_user_id' => $otherUser->id
]);
$item = PlannableItem::factory()->create([
'trip_id' => $otherTrip->id
]);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
'Accept' => 'application/json'
])->putJson("/api/plannables/{$item->id}", [
'name' => 'Hacked Name'
]);
$response->assertStatus(403);
}
public function test_validates_required_fields_when_creating_plannable_item()
{
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
'Accept' => 'application/json'
])->postJson("/api/trips/{$this->trip->id}/plannables", []);
$response->assertStatus(422)
->assertJsonValidationErrors(['name', 'type']);
}
public function test_validates_type_enum_values()
{
$data = [
'name' => 'Test Item',
'type' => 'invalid_type'
];
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
'Accept' => 'application/json'
])->postJson("/api/trips/{$this->trip->id}/plannables", $data);
$response->assertStatus(422)
->assertJsonValidationErrors(['type']);
}
}