118 lines
3.7 KiB
PHP
118 lines
3.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\Artwork;
|
|
use App\Models\User;
|
|
|
|
beforeEach(function () {
|
|
// Use null Scout driver so no Meilisearch calls are made
|
|
config(['scout.driver' => 'null']);
|
|
});
|
|
|
|
// ── 404 cases ─────────────────────────────────────────────────────────────────
|
|
|
|
it('returns 404 for a non-existent artwork id', function () {
|
|
$this->getJson('/api/art/99999/similar')
|
|
->assertStatus(404)
|
|
->assertJsonPath('error', 'Artwork not found');
|
|
});
|
|
|
|
it('returns 404 for a private artwork', function () {
|
|
$artwork = Artwork::factory()->create(['is_public' => false]);
|
|
|
|
$this->getJson("/api/art/{$artwork->id}/similar")
|
|
->assertStatus(404);
|
|
});
|
|
|
|
it('returns 404 for an unapproved artwork', function () {
|
|
$artwork = Artwork::factory()->create(['is_approved' => false]);
|
|
|
|
$this->getJson("/api/art/{$artwork->id}/similar")
|
|
->assertStatus(404);
|
|
});
|
|
|
|
it('returns 404 for an unpublished artwork', function () {
|
|
$artwork = Artwork::factory()->unpublished()->create();
|
|
|
|
$this->getJson("/api/art/{$artwork->id}/similar")
|
|
->assertStatus(404);
|
|
});
|
|
|
|
// ── Success cases ─────────────────────────────────────────────────────────────
|
|
|
|
it('returns a data array for a valid public artwork', function () {
|
|
$artwork = Artwork::factory()->create([
|
|
'is_public' => true,
|
|
'is_approved' => true,
|
|
'published_at' => now()->subDay(),
|
|
]);
|
|
|
|
$response = $this->getJson("/api/art/{$artwork->id}/similar");
|
|
|
|
$response->assertStatus(200);
|
|
$response->assertJsonStructure(['data']);
|
|
expect($response->json('data'))->toBeArray();
|
|
});
|
|
|
|
it('the source artwork id is never present in results', function () {
|
|
$artwork = Artwork::factory()->create([
|
|
'is_public' => true,
|
|
'is_approved' => true,
|
|
'published_at' => now()->subDay(),
|
|
]);
|
|
|
|
$ids = collect($this->getJson("/api/art/{$artwork->id}/similar")->json('data'))
|
|
->pluck('id')
|
|
->all();
|
|
|
|
expect($ids)->not->toContain($artwork->id);
|
|
});
|
|
|
|
it('result count does not exceed 12', function () {
|
|
$artwork = Artwork::factory()->create([
|
|
'is_public' => true,
|
|
'is_approved' => true,
|
|
'published_at' => now()->subDay(),
|
|
]);
|
|
|
|
$count = count($this->getJson("/api/art/{$artwork->id}/similar")->json('data'));
|
|
|
|
// null Scout driver returns 0 results; max is 12
|
|
expect($count <= 12)->toBeTrue();
|
|
});
|
|
|
|
it('results do not include artworks by the same creator', function () {
|
|
$creatorA = User::factory()->create();
|
|
$creatorB = User::factory()->create();
|
|
|
|
$source = Artwork::factory()->create([
|
|
'user_id' => $creatorA->id,
|
|
'is_public' => true,
|
|
'is_approved' => true,
|
|
'published_at' => now()->subDay(),
|
|
]);
|
|
|
|
// A matching artwork from a different creator
|
|
Artwork::factory()->create([
|
|
'user_id' => $creatorB->id,
|
|
'is_public' => true,
|
|
'is_approved' => true,
|
|
'published_at' => now()->subDay(),
|
|
]);
|
|
|
|
$response = $this->getJson("/api/art/{$source->id}/similar");
|
|
$response->assertStatus(200);
|
|
|
|
$items = $response->json('data');
|
|
|
|
// With null Scout driver the search returns 0 items; if items are present
|
|
// none should belong to the source artwork's creator.
|
|
foreach ($items as $item) {
|
|
expect($item)->toHaveKeys(['id', 'title', 'slug', 'thumb', 'url', 'author_id']);
|
|
expect($item['author_id'])->not->toBe($creatorA->id);
|
|
}
|
|
|
|
expect(true)->toBeTrue(); // always at least one assertion
|
|
});
|