create(array_merge([ 'title' => 'World History ' . strtolower(fake()->bothify('####')), 'slug' => 'world-history-' . strtolower(fake()->bothify('####')), 'status' => World::STATUS_PUBLISHED, 'published_at' => now()->subDay(), ], $overrides)); } function createPublicArtworkForProfileHistory(User $creator, array $overrides = []): Artwork { return Artwork::factory()->for($creator)->create(array_merge([ 'title' => 'World Artwork ' . strtolower(fake()->bothify('####')), 'slug' => 'world-artwork-' . strtolower(fake()->bothify('####')), 'artwork_status' => 'published', 'published_at' => now()->subDay(), 'is_public' => true, 'visibility' => Artwork::VISIBILITY_PUBLIC, 'is_approved' => true, ], $overrides)); } it('exposes normalized world history on public profile pages', function (): void { $creator = User::factory()->create([ 'username' => 'worldhist-' . strtolower(fake()->bothify('####')), ]); $groupOwner = User::factory()->create(); $group = Group::factory()->create([ 'owner_user_id' => $groupOwner->id, 'visibility' => Group::VISIBILITY_PUBLIC, 'status' => Group::LIFECYCLE_ACTIVE, ]); $challenge = GroupChallenge::query()->create([ 'group_id' => $group->id, 'title' => 'Autumn Finals', 'slug' => 'autumn-finals-' . strtolower(fake()->bothify('####')), 'summary' => 'Final round challenge.', 'description' => 'Final round challenge.', 'visibility' => GroupChallenge::VISIBILITY_PUBLIC, 'participation_scope' => GroupChallenge::PARTICIPATION_PUBLIC, 'status' => GroupChallenge::STATUS_ACTIVE, 'start_at' => now()->subDays(2), 'end_at' => now()->addDays(2), 'created_by_user_id' => $groupOwner->id, ]); $world = createPublicWorldForProfileHistory([ 'title' => 'Autumn Finals 2026', 'slug' => 'autumn-finals-2026-' . strtolower(fake()->bothify('####')), 'linked_challenge_id' => $challenge->id, 'recurrence_key' => 'autumn-finals', 'edition_year' => 2026, ]); $artwork = createPublicArtworkForProfileHistory($creator, [ 'title' => 'Autumn Skyline', 'slug' => 'autumn-skyline-' . strtolower(fake()->bothify('####')), ]); WorldSubmission::query()->create([ 'world_id' => $world->id, 'artwork_id' => $artwork->id, 'submitted_by_user_id' => $creator->id, 'status' => WorldSubmission::STATUS_LIVE, 'is_featured' => false, 'reviewed_at' => now()->subDay(), ]); GroupChallengeOutcome::query()->create([ 'group_challenge_id' => $challenge->id, 'artwork_id' => $artwork->id, 'user_id' => $creator->id, 'outcome_type' => GroupChallengeOutcome::TYPE_WINNER, 'awarded_by_user_id' => $groupOwner->id, 'awarded_at' => now()->subHour(), ]); $this->get(route('profile.show', ['username' => strtolower((string) $creator->username)])) ->assertOk() ->assertInertia(fn (AssertableInertia $page) => $page ->component('Profile/ProfileShow') ->where('worldHistory.summary.available', true) ->where('worldHistory.summary.world_appearances', 1) ->where('worldHistory.summary.worlds_joined', 1) ->where('worldHistory.summary.winner_appearances', 1) ->where('worldHistory.summary.most_recent_world_activity.primary_recognition.key', 'winner') ->where('worldHistory.entries.0.world.title', 'Autumn Finals 2026') ->where('worldHistory.entries.0.primary_recognition.key', 'winner') ->where('worldHistory.entries.0.recognition_keys.0', 'winner') ->where('worldHistory.entries.0.challenge.title', 'Autumn Finals') ->where('worldHistory.entries.0.linked_artwork.title', 'Autumn Skyline')); }); it('filters stale public world rewards while preserving owner-only context counts', function (): void { $creator = User::factory()->create([ 'username' => 'worldfilter-' . strtolower(fake()->bothify('####')), ]); $staleWorld = createPublicWorldForProfileHistory([ 'title' => 'Removed Entry World', 'slug' => 'removed-entry-world-' . strtolower(fake()->bothify('####')), ]); $pendingWorld = createPublicWorldForProfileHistory([ 'title' => 'Pending Entry World', 'slug' => 'pending-entry-world-' . strtolower(fake()->bothify('####')), ]); $removedArtwork = createPublicArtworkForProfileHistory($creator, [ 'title' => 'Removed Entry Artwork', 'slug' => 'removed-entry-artwork-' . strtolower(fake()->bothify('####')), ]); $pendingArtwork = createPublicArtworkForProfileHistory($creator, [ 'title' => 'Pending Entry Artwork', 'slug' => 'pending-entry-artwork-' . strtolower(fake()->bothify('####')), ]); $removedSubmission = WorldSubmission::query()->create([ 'world_id' => $staleWorld->id, 'artwork_id' => $removedArtwork->id, 'submitted_by_user_id' => $creator->id, 'status' => WorldSubmission::STATUS_REMOVED, 'removed_at' => now()->subHour(), ]); WorldRewardGrant::query()->create([ 'user_id' => $creator->id, 'world_id' => $staleWorld->id, 'artwork_id' => $removedArtwork->id, 'world_submission_id' => $removedSubmission->id, 'reward_type' => 'participant', 'grant_source' => 'automatic', 'granted_at' => now()->subMinutes(30), ]); WorldSubmission::query()->create([ 'world_id' => $pendingWorld->id, 'artwork_id' => $pendingArtwork->id, 'submitted_by_user_id' => $creator->id, 'status' => WorldSubmission::STATUS_PENDING, ]); $this->get(route('profile.show', ['username' => strtolower((string) $creator->username)])) ->assertOk() ->assertInertia(fn (AssertableInertia $page) => $page ->component('Profile/ProfileShow') ->where('worldHistory.summary.available', false) ->where('worldHistory.entries', []) ->where('worldHistory.owner_context', null)); $this->actingAs($creator) ->get(route('profile.show', ['username' => strtolower((string) $creator->username)])) ->assertOk() ->assertInertia(fn (AssertableInertia $page) => $page ->component('Profile/ProfileShow') ->where('worldHistory.summary.available', false) ->where('worldHistory.owner_context.pending_submissions', 1) ->where('worldHistory.owner_context.removed_or_blocked_submissions', 1) ->where('worldHistory.owner_context.hidden_public_entries', 1)); }); it('supports the canonical worlds profile tab route', function (): void { $creator = User::factory()->create([ 'username' => 'worldtab-' . strtolower(fake()->bothify('####')), ]); $world = createPublicWorldForProfileHistory([ 'title' => 'Featured Worlds 2026', 'slug' => 'featured-worlds-2026-' . strtolower(fake()->bothify('####')), 'edition_year' => 2026, ]); $artwork = createPublicArtworkForProfileHistory($creator, [ 'title' => 'Featured Worlds Artwork', 'slug' => 'featured-worlds-artwork-' . strtolower(fake()->bothify('####')), ]); $submission = WorldSubmission::query()->create([ 'world_id' => $world->id, 'artwork_id' => $artwork->id, 'submitted_by_user_id' => $creator->id, 'status' => WorldSubmission::STATUS_LIVE, 'is_featured' => true, 'featured_at' => now()->subMinutes(10), ]); WorldRewardGrant::query()->create([ 'user_id' => $creator->id, 'world_id' => $world->id, 'artwork_id' => $artwork->id, 'world_submission_id' => $submission->id, 'reward_type' => 'featured', 'grant_source' => 'automatic', 'granted_at' => now()->subMinutes(5), ]); $this->get(route('profile.tab', ['username' => strtolower((string) $creator->username), 'tab' => 'worlds'])) ->assertOk() ->assertInertia(fn (AssertableInertia $page) => $page ->component('Profile/ProfileShow') ->where('initialTab', 'worlds') ->where('profileTabUrls.worlds', url('/@' . strtolower((string) $creator->username) . '/worlds')) ->where('worldHistory.summary.available', true) ->where('worldHistory.entries.0.primary_recognition.key', 'featured')); });