feat: ship creator journey v2 and profile updates

This commit is contained in:
2026-04-12 21:42:07 +02:00
parent a2457f4e49
commit d5cff21ea2
335 changed files with 20147 additions and 1545 deletions

View File

@@ -39,45 +39,52 @@ it('records a view and returns ok=true on first call', function () {
DB::table('artwork_stats')->insertOrIgnore([
'artwork_id' => $artwork->id,
'views' => 0,
'views_24h' => 0,
'views_7d' => 0,
'downloads' => 0,
'favorites' => 0,
'rating_avg' => 0,
'rating_count' => 0,
]);
$mock = $this->mock(ArtworkStatsService::class);
$mock->shouldReceive('logViewEvent')
->once()
->with($artwork->id, null); // null = guest (unauthenticated request)
$mock->shouldReceive('incrementViews')
->once()
->with($artwork->id, 1, true);
$response = $this->postJson("/api/art/{$artwork->id}/view");
$response->assertStatus(200)
->assertJsonPath('ok', true)
->assertJsonPath('counted', true);
expect(DB::table('artwork_stats')->where('artwork_id', $artwork->id)->value('views'))->toBe(1);
expect(DB::table('artwork_view_events')->where('artwork_id', $artwork->id)->count())->toBe(1);
});
it('skips DB increment and returns counted=false if artwork was already viewed this session', function () {
it('counts repeated visits for the same artwork', function () {
$artwork = Artwork::factory()->create([
'is_public' => true,
'is_approved' => true,
'published_at' => now()->subDay(),
]);
// Mark as already viewed in the session
session()->put("art_viewed.{$artwork->id}", true);
DB::table('artwork_stats')->insertOrIgnore([
'artwork_id' => $artwork->id,
'views' => 0,
'views_24h' => 0,
'views_7d' => 0,
'downloads' => 0,
'favorites' => 0,
'rating_avg' => 0,
'rating_count' => 0,
]);
$mock = $this->mock(ArtworkStatsService::class);
$mock->shouldReceive('incrementViews')->never();
$this->postJson("/api/art/{$artwork->id}/view")
->assertStatus(200)
->assertJsonPath('counted', true);
$response = $this->postJson("/api/art/{$artwork->id}/view");
$this->postJson("/api/art/{$artwork->id}/view")
->assertStatus(200)
->assertJsonPath('counted', true);
$response->assertStatus(200)
->assertJsonPath('ok', true)
->assertJsonPath('counted', false);
expect(DB::table('artwork_stats')->where('artwork_id', $artwork->id)->value('views'))->toBe(2);
expect(DB::table('artwork_view_events')->where('artwork_id', $artwork->id)->count())->toBe(2);
});
// ── ArtworkDownloadController (POST /api/art/{id}/download) ──────────────────
@@ -101,7 +108,7 @@ it('records a download and returns ok=true with a url', function () {
$mock = $this->mock(ArtworkStatsService::class);
$mock->shouldReceive('incrementDownloads')
->once()
->with($artwork->id, 1, true);
->with($artwork->id, 1, false);
$response = $this->postJson("/api/art/{$artwork->id}/download");
@@ -120,7 +127,7 @@ it('inserts a row in artwork_downloads on valid download', function () {
// Stub the stats service so we don't need Redis
$mock = $this->mock(ArtworkStatsService::class);
$mock->shouldReceive('incrementDownloads')->once();
$mock->shouldReceive('incrementDownloads')->once()->with($artwork->id, 1, false);
$this->actingAs($user)->postJson("/api/art/{$artwork->id}/download");
@@ -138,7 +145,7 @@ it('records download as guest (no user_id) when unauthenticated', function () {
]);
$mock = $this->mock(ArtworkStatsService::class);
$mock->shouldReceive('incrementDownloads')->once();
$mock->shouldReceive('incrementDownloads')->once()->with($artwork->id, 1, false);
$this->postJson("/api/art/{$artwork->id}/download");