Files
landing-api/tests/Feature/Api/SearchApiTest.php
Josep Piguillem 6b3517743a Search the public site through the API
Full-text on Postgres, stemmed in the language searched; word matching
elsewhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 08:53:34 +02:00

81 lines
3.0 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Feature\Api;
use App\Models\Member;
use App\Models\Page;
use App\Models\Project;
use App\Models\Technology;
use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
* GET /public/v1/search — run here on SQLite, so through the word-matching
* fallback; the shape and the rules about what is visible are the same.
*/
class SearchApiTest extends TestCase
{
use RefreshDatabase;
#[Test]
public function it_finds_published_content_in_the_language_asked(): void
{
Project::factory()->published()->create([
'title' => ['es' => 'Catálogo abierto', 'en' => 'Open catalogue'],
'slug' => ['es' => 'catalogo', 'en' => 'catalogue'],
'tagline' => ['es' => 'Una herramienta para bibliotecas.', 'en' => 'A tool for libraries.'],
]);
Page::factory()->published()->create([
'title' => ['es' => 'Bibliotecas libres'],
'slug' => ['es' => 'bibliotecas'],
'body' => ['es' => '<p>Sobre <strong>bibliotecas</strong>.</p>'],
]);
$response = $this->getJson('/api/public/v1/search?lang=es&q=bibliotecas')
->assertOk()
->assertJsonCount(2, 'data')
->assertJsonPath('meta.count', 2);
// The title match first.
$response->assertJsonPath('data.0.type', 'page')
->assertJsonPath('data.0.path', '/bibliotecas');
$this->getJson('/api/public/v1/search?q=libraries&lang=en')
->assertJsonCount(1, 'data')
->assertJsonPath('data.0.title', 'Open catalogue')
->assertJsonPath('data.0.path', '/en/projects/catalogue');
}
#[Test]
public function drafts_and_private_people_are_not_found(): void
{
Page::factory()->draft()->create(['title' => ['es' => 'Borrador secreto'], 'slug' => ['es' => 'borrador']]);
Member::factory()->create(['name' => 'Secreto Oculto', 'slug' => 'oculto', 'is_public' => false]);
Technology::factory()->create(['name' => 'Secretlang']);
$this->getJson('/api/public/v1/search?lang=es&q=secret')->assertOk()->assertJsonCount(0, 'data');
}
#[Test]
public function every_word_has_to_match_and_types_can_be_narrowed(): void
{
Project::factory()->published()->create(['title' => ['es' => 'Radar técnico'], 'slug' => ['es' => 'radar']]);
Page::factory()->published()->create(['title' => ['es' => 'Radar de tecnologías'], 'slug' => ['es' => 'radar-pagina']]);
$this->getJson('/api/public/v1/search?lang=es&q=radar+técnico')->assertJsonCount(1, 'data');
$this->getJson('/api/public/v1/search?lang=es&q=radar&type[]=page')
->assertJsonCount(1, 'data')
->assertJsonPath('data.0.type', 'page');
}
#[Test]
public function a_query_is_required(): void
{
$this->getJson('/api/public/v1/search')->assertUnprocessable()->assertJsonValidationErrors('q');
$this->getJson('/api/public/v1/search?q=a')->assertUnprocessable();
}
}