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); } }