188 lines
5.6 KiB
PHP
188 lines
5.6 KiB
PHP
|
|
<?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']);
|
||
|
|
}
|
||
|
|
}
|