Upload beautify
This commit is contained in:
104
tests/Feature/Admin/FeedPerformanceReportTest.php
Normal file
104
tests/Feature/Admin/FeedPerformanceReportTest.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Models\Artwork;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('admin report returns feed performance breakdown and top clicked artworks', function () {
|
||||
$admin = User::factory()->create(['role' => 'admin']);
|
||||
|
||||
$artworkA = Artwork::factory()->create(['title' => 'Feed Artwork A']);
|
||||
$artworkB = Artwork::factory()->create(['title' => 'Feed Artwork B']);
|
||||
|
||||
$metricDate = now()->subDay()->toDateString();
|
||||
|
||||
DB::table('feed_daily_metrics')->insert([
|
||||
[
|
||||
'metric_date' => $metricDate,
|
||||
'algo_version' => 'clip-cosine-v1',
|
||||
'source' => 'personalized',
|
||||
'impressions' => 10,
|
||||
'clicks' => 4,
|
||||
'saves' => 2,
|
||||
'ctr' => 0.4,
|
||||
'save_rate' => 0.5,
|
||||
'dwell_0_5' => 1,
|
||||
'dwell_5_30' => 1,
|
||||
'dwell_30_120' => 1,
|
||||
'dwell_120_plus' => 1,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
],
|
||||
]);
|
||||
|
||||
DB::table('feed_events')->insert([
|
||||
[
|
||||
'event_date' => $metricDate,
|
||||
'event_type' => 'feed_impression',
|
||||
'user_id' => $admin->id,
|
||||
'artwork_id' => $artworkA->id,
|
||||
'position' => 1,
|
||||
'algo_version' => 'clip-cosine-v1',
|
||||
'source' => 'personalized',
|
||||
'dwell_seconds' => null,
|
||||
'occurred_at' => now()->subDay(),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
],
|
||||
[
|
||||
'event_date' => $metricDate,
|
||||
'event_type' => 'feed_click',
|
||||
'user_id' => $admin->id,
|
||||
'artwork_id' => $artworkA->id,
|
||||
'position' => 1,
|
||||
'algo_version' => 'clip-cosine-v1',
|
||||
'source' => 'personalized',
|
||||
'dwell_seconds' => 12,
|
||||
'occurred_at' => now()->subDay(),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
],
|
||||
[
|
||||
'event_date' => $metricDate,
|
||||
'event_type' => 'feed_click',
|
||||
'user_id' => $admin->id,
|
||||
'artwork_id' => $artworkB->id,
|
||||
'position' => 2,
|
||||
'algo_version' => 'clip-cosine-v1',
|
||||
'source' => 'personalized',
|
||||
'dwell_seconds' => 7,
|
||||
'occurred_at' => now()->subDay(),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($admin)->getJson('/api/admin/reports/feed-performance?from=' . $metricDate . '&to=' . $metricDate);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('meta.from', $metricDate);
|
||||
$response->assertJsonPath('meta.to', $metricDate);
|
||||
|
||||
$rows = collect($response->json('by_algo_source'));
|
||||
expect($rows->count())->toBe(1);
|
||||
expect($rows->first()['algo_version'])->toBe('clip-cosine-v1');
|
||||
expect($rows->first()['source'])->toBe('personalized');
|
||||
expect((float) $rows->first()['ctr'])->toBe(0.4);
|
||||
|
||||
$top = collect($response->json('top_clicked_artworks'));
|
||||
expect($top->isNotEmpty())->toBeTrue();
|
||||
expect((int) $top->first()['artwork_id'])->toBe($artworkA->id);
|
||||
});
|
||||
|
||||
it('non-admin is denied feed performance report endpoint', function () {
|
||||
$user = User::factory()->create(['role' => 'user']);
|
||||
|
||||
$response = $this->actingAs($user)->getJson('/api/admin/reports/feed-performance');
|
||||
|
||||
$response->assertStatus(403);
|
||||
});
|
||||
Reference in New Issue
Block a user