177 lines
4.5 KiB
PHP
177 lines
4.5 KiB
PHP
<?php
|
|||
|
|
|
||
|
|
namespace Tests\Feature;
|
||
|
|
|
||
|
|
use App\Models\City;
|
||
|
|
use App\Models\Attraction;
|
||
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||
|
|
use Tests\TestCase;
|
||
|
|
|
||
|
|
class CityApiTest extends TestCase
|
||
|
|
{
|
||
|
|
use RefreshDatabase;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test city search returns local results
|
||
|
|
*/
|
||
|
|
public function test_city_search_returns_local_results(): void
|
||
|
|
{
|
||
|
|
$city = City::factory()->create([
|
||
|
|
'name' => 'Paris',
|
||
|
|
'country' => 'France',
|
||
|
|
]);
|
||
|
|
|
||
|
|
$response = $this->getJson('/api/cities/search?q=Paris');
|
||
|
|
|
||
|
|
$response->assertStatus(200)
|
||
|
|
->assertJsonStructure([
|
||
|
|
'local' => [
|
||
|
|
'*' => ['id', 'name', 'country']
|
||
|
|
],
|
||
|
|
])
|
||
|
|
->assertJsonFragment([
|
||
|
|
'name' => 'Paris',
|
||
|
|
'country' => 'France',
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test city search validation
|
||
|
|
*/
|
||
|
|
public function test_city_search_requires_query_parameter(): void
|
||
|
|
{
|
||
|
|
$response = $this->getJson('/api/cities/search');
|
||
|
|
|
||
|
|
$response->assertStatus(422)
|
||
|
|
->assertJsonValidationErrors(['q']);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test city search query minimum length
|
||
|
|
*/
|
||
|
|
public function test_city_search_query_has_minimum_length(): void
|
||
|
|
{
|
||
|
|
$response = $this->getJson('/api/cities/search?q=a');
|
||
|
|
|
||
|
|
$response->assertStatus(422)
|
||
|
|
->assertJsonValidationErrors(['q']);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test showing a specific city
|
||
|
|
*/
|
||
|
|
public function test_show_city_returns_city_data(): void
|
||
|
|
{
|
||
|
|
$city = City::factory()->create([
|
||
|
|
'name' => 'Tokyo',
|
||
|
|
'country' => 'Japan',
|
||
|
|
'latitude' => 35.6762,
|
||
|
|
'longitude' => 139.6503,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$response = $this->getJson("/api/cities/{$city->id}");
|
||
|
|
|
||
|
|
$response->assertStatus(200)
|
||
|
|
->assertJsonFragment([
|
||
|
|
'name' => 'Tokyo',
|
||
|
|
'country' => 'Japan',
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test getting attractions for a city
|
||
|
|
*/
|
||
|
|
public function test_city_attractions_returns_attractions(): void
|
||
|
|
{
|
||
|
|
$city = City::factory()->create();
|
||
|
|
$attractions = Attraction::factory()->count(5)->create([
|
||
|
|
'city_id' => $city->id,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$response = $this->getJson("/api/cities/{$city->id}/attractions");
|
||
|
|
|
||
|
|
$response->assertStatus(200)
|
||
|
|
->assertJsonCount(5, 'data');
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test attractions pagination
|
||
|
|
*/
|
||
|
|
public function test_attractions_are_paginated(): void
|
||
|
|
{
|
||
|
|
$city = City::factory()->create();
|
||
|
|
Attraction::factory()->count(30)->create([
|
||
|
|
'city_id' => $city->id,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$response = $this->getJson("/api/cities/{$city->id}/attractions?limit=10");
|
||
|
|
|
||
|
|
$response->assertStatus(200)
|
||
|
|
->assertJsonCount(10, 'data')
|
||
|
|
->assertJsonStructure([
|
||
|
|
'data',
|
||
|
|
'current_page',
|
||
|
|
'last_page',
|
||
|
|
'per_page',
|
||
|
|
'total',
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test attractions filtering by category
|
||
|
|
*/
|
||
|
|
public function test_attractions_can_be_filtered_by_category(): void
|
||
|
|
{
|
||
|
|
$city = City::factory()->create();
|
||
|
|
|
||
|
|
Attraction::factory()->count(3)->create([
|
||
|
|
'city_id' => $city->id,
|
||
|
|
'category' => 'museum',
|
||
|
|
]);
|
||
|
|
|
||
|
|
Attraction::factory()->count(2)->create([
|
||
|
|
'city_id' => $city->id,
|
||
|
|
'category' => 'restaurant',
|
||
|
|
]);
|
||
|
|
|
||
|
|
$response = $this->getJson("/api/cities/{$city->id}/attractions?category=museum");
|
||
|
|
|
||
|
|
$response->assertStatus(200)
|
||
|
|
->assertJsonCount(3, 'data');
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test getting map data for a city
|
||
|
|
*/
|
||
|
|
public function test_city_map_data_returns_coordinates(): void
|
||
|
|
{
|
||
|
|
$city = City::factory()->create([
|
||
|
|
'latitude' => 48.8566,
|
||
|
|
'longitude' => 2.3522,
|
||
|
|
]);
|
||
|
|
|
||
|
|
Attraction::factory()->count(3)->create([
|
||
|
|
'city_id' => $city->id,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$response = $this->getJson("/api/cities/{$city->id}/map-data");
|
||
|
|
|
||
|
|
$response->assertStatus(200)
|
||
|
|
->assertJsonStructure([
|
||
|
|
'city' => ['name', 'latitude', 'longitude'],
|
||
|
|
'attractions' => [
|
||
|
|
'*' => ['id', 'name', 'latitude', 'longitude', 'category']
|
||
|
|
],
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test 404 for non-existent city
|
||
|
|
*/
|
||
|
|
public function test_show_city_returns_404_for_non_existent_city(): void
|
||
|
|
{
|
||
|
|
$response = $this->getJson('/api/cities/99999');
|
||
|
|
|
||
|
|
$response->assertStatus(404);
|
||
|
|
}
|
||
|
|
}
|