create(); $artwork = Artwork::withoutEvents(fn () => Artwork::factory()->create([ 'user_id' => $user->id, 'is_approved' => true, 'is_public' => true, 'published_at' => now()->subDays(2), 'deleted_at' => null, ])); $currentHour = now()->startOfHour(); $prevHour = $currentHour->copy()->subHour(); ArtworkMetricSnapshotHourly::create([ 'artwork_id' => $artwork->id, 'bucket_hour' => $prevHour, 'views_count' => 10, 'downloads_count' => 1, 'favourites_count' => 1, 'comments_count' => 0, 'shares_count' => 0, ]); ArtworkMetricSnapshotHourly::create([ 'artwork_id' => $artwork->id, 'bucket_hour' => $currentHour, 'views_count' => 40, 'downloads_count' => 4, 'favourites_count' => 3, 'comments_count' => 1, 'shares_count' => 1, ]); $this->artisan('nova:recalculate-heat', ['--chunk' => 1])->assertExitCode(0); $row = DB::table('artwork_stats')->where('artwork_id', $artwork->id)->first(); expect($row)->not->toBeNull() ->and((float) $row->heat_score)->toBeGreaterThan(0); });