Files
SkinbaseNova/tests/Feature/Discovery/DiscoveryEventIngestionTest.php
2026-03-28 19:15:39 +01:00

68 lines
2.0 KiB
PHP

<?php
declare(strict_types=1);
use App\Jobs\IngestUserDiscoveryEventJob;
use App\Models\Artwork;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue;
uses(RefreshDatabase::class);
it('queues discovery event ingestion asynchronously', function () {
Queue::fake();
$user = User::factory()->create();
$artwork = Artwork::factory()->create();
$response = $this->actingAs($user)->postJson('/api/discovery/events', [
'event_type' => 'view',
'artwork_id' => $artwork->id,
'meta' => ['source' => 'artwork_show'],
]);
$response
->assertStatus(202)
->assertJsonPath('queued', true)
->assertJsonPath('algo_version', (string) config('discovery.algo_version'));
Queue::assertPushed(IngestUserDiscoveryEventJob::class, function (IngestUserDiscoveryEventJob $job) use ($user, $artwork): bool {
return $job->userId === $user->id
&& $job->artworkId === $artwork->id
&& $job->eventType === 'view';
});
});
it('validates discovery event payload', function () {
$user = User::factory()->create();
$artwork = Artwork::factory()->create();
$response = $this->actingAs($user)->postJson('/api/discovery/events', [
'event_type' => 'impression',
'artwork_id' => $artwork->id,
]);
$response->assertStatus(422);
$response->assertJsonValidationErrors(['event_type']);
});
it('accepts session-oriented discovery events', function () {
Queue::fake();
$user = User::factory()->create();
$artwork = Artwork::factory()->create();
$response = $this->actingAs($user)->postJson('/api/discovery/events', [
'event_type' => 'dwell',
'artwork_id' => $artwork->id,
'meta' => ['duration_ms' => 4500],
]);
$response->assertStatus(202);
Queue::assertPushed(IngestUserDiscoveryEventJob::class, function (IngestUserDiscoveryEventJob $job): bool {
return $job->eventType === 'dwell';
});
});