create(); $source = Artwork::factory()->create(['user_id' => $author->id]); $similar = Artwork::factory()->create(['user_id' => $author->id]); $response = $this->postJson('/api/analytics/similar-artworks', [ 'event_type' => 'click', 'algo_version' => 'clip-cosine-v1', 'source_artwork_id' => $source->id, 'similar_artwork_id' => $similar->id, 'position' => 2, ]); $response->assertOk()->assertJson(['success' => true]); $this->assertDatabaseHas('similar_artwork_events', [ 'event_type' => 'click', 'algo_version' => 'clip-cosine-v1', 'source_artwork_id' => $source->id, 'similar_artwork_id' => $similar->id, 'position' => 2, ]); }); it('aggregates daily analytics counts by algo version', function () { DB::table('similar_artwork_events')->insert([ [ 'event_date' => now()->subDay()->toDateString(), 'event_type' => 'impression', 'algo_version' => 'clip-cosine-v1', 'source_artwork_id' => Artwork::factory()->create()->id, 'similar_artwork_id' => null, 'position' => null, 'items_count' => 8, 'occurred_at' => now()->subDay(), 'created_at' => now(), 'updated_at' => now(), ], [ 'event_date' => now()->subDay()->toDateString(), 'event_type' => 'click', 'algo_version' => 'clip-cosine-v1', 'source_artwork_id' => Artwork::factory()->create()->id, 'similar_artwork_id' => Artwork::factory()->create()->id, 'position' => 1, 'items_count' => null, 'occurred_at' => now()->subDay(), 'created_at' => now(), 'updated_at' => now(), ], ]); $this->artisan('analytics:aggregate-similar-artworks', ['--date' => now()->subDay()->toDateString()]) ->assertSuccessful(); $this->assertDatabaseHas('similar_artwork_daily_metrics', [ 'metric_date' => now()->subDay()->toDateString(), 'algo_version' => 'clip-cosine-v1', 'impressions' => 1, 'clicks' => 1, ]); });