create(); $owner = User::factory()->create(); $titleMatch = MealPosts::factory()->for($owner, 'user')->create([ 'title' => 'Bowl méditerranéen', 'visibility' => MealPostVisibility::Public, ]); $ingredientMatch = MealPosts::factory()->for($owner, 'user')->create([ 'title' => 'Déjeuner coloré', 'caption' => 'Simple et frais', 'visibility' => MealPostVisibility::Public, ]); $ingredientMatch->ingredients()->create([ 'ingredient' => 'Tomates cerises', 'position' => 0, 'quantity' => 100, 'unit' => 'g', ]); MealPosts::factory()->for($owner, 'user')->create([ 'title' => 'Bowl privé', 'visibility' => MealPostVisibility::Private, ]); Sanctum::actingAs($viewer); $this->getJson('/api/search?q=bowl&type=meals&per_page=1') ->assertOk() ->assertJsonCount(1, 'data') ->assertJsonPath('data.0.id', $titleMatch->id) ->assertJsonPath('meta.total', 1); $this->getJson('/api/search?q=tomates&type=meals') ->assertOk() ->assertJsonCount(1, 'data') ->assertJsonPath('data.0.id', $ingredientMatch->id); }); it('searches users while excluding suspended and blocked accounts', function () { $viewer = User::factory()->create(['name' => 'viewer']); $visible = User::factory()->create(['name' => 'alex_bowli', 'bio' => 'Cuisine végétale']); $blocked = User::factory()->create(['name' => 'alex_blocked']); User::factory()->create(['name' => 'alex_suspended', 'suspended_at' => now()]); $viewer->blockedUsers()->attach($blocked); Sanctum::actingAs($viewer); $this->getJson('/api/search?q=alex&type=users') ->assertOk() ->assertJsonCount(1, 'data') ->assertJsonPath('data.0.id', $visible->id) ->assertJsonMissing(['id' => $blocked->id]); }); it('validates the search query and result type', function () { Sanctum::actingAs(User::factory()->create()); $this->getJson('/api/search?q=a&type=unknown') ->assertUnprocessable() ->assertJsonValidationErrors(['q', 'type']); });