119 lines
3.5 KiB
PHP
119 lines
3.5 KiB
PHP
<?php
|
|
|
|
use App\Models\Artwork;
|
|
use App\Models\ArtworkStats;
|
|
use App\Models\Category;
|
|
use App\Models\ContentType;
|
|
use App\Models\User;
|
|
use Illuminate\Pagination\Cursor;
|
|
|
|
it('supports cursor pagination for latest profile artworks', function () {
|
|
[$user] = seedProfileArtworksApiFixtures(26);
|
|
|
|
$firstPage = $this->getJson("/api/profile/{$user->username}/artworks");
|
|
|
|
$firstPage->assertOk();
|
|
$firstPage->assertJsonCount(24, 'data');
|
|
|
|
$nextCursor = $firstPage->json('next_cursor');
|
|
|
|
expect($nextCursor)->not->toBeNull();
|
|
|
|
$secondPage = $this->getJson("/api/profile/{$user->username}/artworks?cursor={$nextCursor}");
|
|
|
|
$secondPage->assertOk();
|
|
$secondPage->assertJsonCount(2, 'data');
|
|
});
|
|
|
|
it('supports cursor pagination for stats-sorted profile artworks', function () {
|
|
[$user] = seedProfileArtworksApiFixtures(26);
|
|
|
|
$firstPage = $this->getJson("/api/profile/{$user->username}/artworks?sort=views");
|
|
|
|
$firstPage->assertOk();
|
|
$firstPage->assertJsonCount(24, 'data');
|
|
|
|
$nextCursor = $firstPage->json('next_cursor');
|
|
|
|
expect($nextCursor)->not->toBeNull();
|
|
|
|
$secondPage = $this->getJson("/api/profile/{$user->username}/artworks?sort=views&cursor={$nextCursor}");
|
|
|
|
$secondPage->assertOk();
|
|
$secondPage->assertJsonCount(2, 'data');
|
|
});
|
|
|
|
it('falls back to the first page when a legacy profile artworks cursor is missing id', function () {
|
|
[$user] = seedProfileArtworksApiFixtures(26);
|
|
|
|
$legacyCursor = new Cursor([
|
|
'published_at' => Artwork::query()->orderByDesc('published_at')->value('published_at')?->format(DATE_ATOM),
|
|
]);
|
|
|
|
$response = $this->getJson("/api/profile/{$user->username}/artworks?cursor={$legacyCursor->encode()}");
|
|
|
|
$response->assertOk();
|
|
$response->assertJsonCount(24, 'data');
|
|
expect($response->json('next_cursor'))->not->toBeNull();
|
|
});
|
|
|
|
function seedProfileArtworksApiFixtures(int $count): array
|
|
{
|
|
$user = User::factory()->create([
|
|
'name' => 'Profile Artist',
|
|
'username' => 'profileartist',
|
|
'email' => 'profileartist@example.test',
|
|
]);
|
|
|
|
$contentType = ContentType::create([
|
|
'name' => 'Skins',
|
|
'slug' => 'skins',
|
|
'description' => 'Skins content type',
|
|
]);
|
|
|
|
$category = Category::create([
|
|
'content_type_id' => $contentType->id,
|
|
'name' => 'Winamp',
|
|
'slug' => 'winamp',
|
|
'description' => 'Winamp skins',
|
|
'is_active' => true,
|
|
'sort_order' => 1,
|
|
]);
|
|
|
|
for ($i = 1; $i <= $count; $i++) {
|
|
$artwork = Artwork::factory()
|
|
->for($user)
|
|
->create([
|
|
'title' => 'Profile Artwork ' . $i,
|
|
'slug' => 'profile-artwork-' . $i,
|
|
'published_at' => now()->subMinutes($i),
|
|
]);
|
|
|
|
$artwork->categories()->attach($category->id);
|
|
|
|
ArtworkStats::create([
|
|
'artwork_id' => $artwork->id,
|
|
'views' => $count - $i,
|
|
'downloads' => $i,
|
|
'favorites' => $i,
|
|
'rating_avg' => 0,
|
|
'rating_count' => 0,
|
|
'comments_count' => 0,
|
|
'shares_count' => 0,
|
|
'ranking_score' => $count - $i,
|
|
'engagement_velocity' => 0,
|
|
'shares_24h' => 0,
|
|
'comments_24h' => 0,
|
|
'favourites_24h' => 0,
|
|
'heat_score' => $count - $i,
|
|
'heat_score_updated_at' => null,
|
|
'views_1h' => 0,
|
|
'favourites_1h' => 0,
|
|
'comments_1h' => 0,
|
|
'shares_1h' => 0,
|
|
'downloads_1h' => 0,
|
|
]);
|
|
}
|
|
|
|
return [$user, $contentType, $category];
|
|
} |