minor fixes

This commit is contained in:
2026-04-09 08:50:36 +02:00
parent 23d363a50c
commit a2457f4e49
75 changed files with 3848 additions and 387 deletions

View File

@@ -3,7 +3,6 @@
use App\Models\Artwork;
use App\Models\ArtworkStats;
use App\Models\ArtworkMetricSnapshotHourly;
use Illuminate\Foundation\Testing\RefreshDatabase;
/**
* Helper: create an artwork row without triggering observers (avoids GREATEST() SQLite issue).
@@ -137,6 +136,92 @@ it('computes heat_score from snapshot deltas', function () {
expect((int) $stat->shares_1h)->toBe(1); // 1 - 0
});
it('smooths heat_score over a wider lookback window while keeping 1h counters exact', function () {
$artwork = createArtworkWithoutObserver([
'is_approved' => true,
'is_public' => true,
'published_at' => now()->subHours(10),
]);
ArtworkStats::upsert([
['artwork_id' => $artwork->id, 'views' => 0, 'downloads' => 0, 'favorites' => 0],
], ['artwork_id']);
$sixHoursAgo = now()->startOfHour()->subHours(6);
$prevHour = now()->startOfHour()->subHour();
$currentHour = now()->startOfHour();
ArtworkMetricSnapshotHourly::create([
'artwork_id' => $artwork->id,
'bucket_hour' => $sixHoursAgo,
'views_count' => 10,
'downloads_count' => 0,
'favourites_count' => 0,
'comments_count' => 0,
'shares_count' => 0,
]);
ArtworkMetricSnapshotHourly::create([
'artwork_id' => $artwork->id,
'bucket_hour' => $prevHour,
'views_count' => 30,
'downloads_count' => 1,
'favourites_count' => 0,
'comments_count' => 0,
'shares_count' => 0,
]);
ArtworkMetricSnapshotHourly::create([
'artwork_id' => $artwork->id,
'bucket_hour' => $currentHour,
'views_count' => 30,
'downloads_count' => 1,
'favourites_count' => 0,
'comments_count' => 0,
'shares_count' => 0,
]);
$this->artisan('nova:recalculate-heat --lookback-hours=6')
->assertSuccessful();
$stat = ArtworkStats::where('artwork_id', $artwork->id)->first();
expect((float) $stat->heat_score)->toBeGreaterThan(0);
expect((int) $stat->views_1h)->toBe(0);
expect((int) $stat->downloads_1h)->toBe(0);
});
it('does not assign heat from a single snapshot without a baseline', function () {
$artwork = createArtworkWithoutObserver([
'is_approved' => true,
'is_public' => true,
'published_at' => now()->subHours(5),
]);
ArtworkStats::upsert([
['artwork_id' => $artwork->id, 'views' => 0, 'downloads' => 0, 'favorites' => 0],
], ['artwork_id']);
ArtworkMetricSnapshotHourly::create([
'artwork_id' => $artwork->id,
'bucket_hour' => now()->startOfHour(),
'views_count' => 300,
'downloads_count' => 25,
'favourites_count' => 4,
'comments_count' => 1,
'shares_count' => 0,
]);
$this->artisan('nova:recalculate-heat --lookback-hours=24')
->assertSuccessful();
$stat = ArtworkStats::where('artwork_id', $artwork->id)->first();
expect((float) $stat->heat_score)->toBe(0.0);
expect((int) $stat->views_1h)->toBe(300);
expect((int) $stat->downloads_1h)->toBe(25);
});
it('handles negative deltas gracefully by clamping to zero', function () {
$artwork = createArtworkWithoutObserver([
'is_approved' => true,