Full-text on Postgres, stemmed in the language searched; word matching elsewhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
81 lines
3.0 KiB
PHP
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();
|
|
}
|
|
}
|