setAccessible(true); return $method->invoke(app(ProfileController::class), $user); } function makeGroupRelease(Group $group, User $creator, string $title, CarbonImmutable $releasedAt, string $visibility = GroupRelease::VISIBILITY_PUBLIC): GroupRelease { return GroupRelease::create([ 'group_id' => $group->id, 'title' => $title, 'slug' => strtolower(str_replace(' ', '-', $title)) . '-' . uniqid(), 'status' => GroupRelease::STATUS_RELEASED, 'current_stage' => GroupRelease::STAGE_RELEASED, 'visibility' => $visibility, 'released_at' => $releasedAt, 'published_at' => $releasedAt, 'created_by_user_id' => $creator->id, ]); } it('preserves contribution output semantics while loading group data in bulk', function (): void { $user = User::factory()->create(); $owner = User::factory()->create(); $group = Group::factory()->create([ 'owner_user_id' => $owner->id, 'name' => 'Visible Contribution Group', 'slug' => 'visible-contribution-group-' . uniqid(), ]); GroupContributorStat::create([ 'group_id' => $group->id, 'user_id' => $user->id, 'credited_artworks_count' => 7, 'release_count' => 5, 'project_count' => 3, 'review_actions_count' => 2, ]); GroupMember::create([ 'group_id' => $group->id, 'user_id' => $user->id, 'role' => Group::ROLE_EDITOR, 'status' => Group::STATUS_ACTIVE, ]); $project = GroupProject::create([ 'group_id' => $group->id, 'title' => 'Visible Project', 'slug' => 'visible-project-' . uniqid(), 'status' => GroupProject::STATUS_ACTIVE, 'visibility' => GroupProject::VISIBILITY_PUBLIC, 'created_by_user_id' => $owner->id, ]); GroupProjectMember::create([ 'group_project_id' => $project->id, 'user_id' => $user->id, 'role_label' => 'Project Lead', 'is_lead' => true, ]); $newest = makeGroupRelease($group, $user, 'Newest Release', CarbonImmutable::parse('2026-08-20 12:00:00')); $middle = makeGroupRelease($group, $owner, 'Middle Release', CarbonImmutable::parse('2026-08-19 12:00:00')); $oldest = makeGroupRelease($group, $owner, 'Oldest Release', CarbonImmutable::parse('2026-08-18 12:00:00')); makeGroupRelease($group, $owner, 'Hidden Release', CarbonImmutable::parse('2026-08-21 12:00:00'), GroupRelease::VISIBILITY_PRIVATE); GroupReleaseContributor::create([ 'group_release_id' => $middle->id, 'user_id' => $user->id, 'role_label' => 'Release Contributor', 'sort_order' => 0, ]); GroupReleaseContributor::create([ 'group_release_id' => $oldest->id, 'user_id' => $user->id, 'role_label' => 'Project Lead', 'sort_order' => 1, ]); $result = invokeGroupContributionHistory($user); expect($result)->toHaveCount(1); expect($result[0]['group'])->toMatchArray([ 'id' => $group->id, 'name' => 'Visible Contribution Group', 'slug' => $group->slug, ]); expect($result[0]['joined_at'])->toBeString(); expect($result[0]['counts'])->toBe([ 'credited_artworks' => 7, 'releases' => 5, 'projects' => 3, 'review_actions' => 2, ]); expect($result[0]['role_labels'])->toBe(['Release Contributor', 'Project Lead']); expect($result[0]['recent_release_titles'])->toBe(['Newest Release', 'Middle Release', 'Oldest Release']); expect($result[0]['role'])->toBe(Group::ROLE_EDITOR); expect($result[0]['trusted_indicator'])->toBeFalse(); }); it('keeps public visibility filtering and owner role semantics', function (): void { $user = User::factory()->create(); $ownerGroup = Group::factory()->create([ 'owner_user_id' => $user->id, 'slug' => 'owner-contribution-group-' . uniqid(), ]); $privateGroup = Group::factory()->private()->create([ 'slug' => 'private-contribution-group-' . uniqid(), ]); GroupContributorStat::create(['group_id' => $ownerGroup->id, 'user_id' => $user->id]); GroupContributorStat::create(['group_id' => $privateGroup->id, 'user_id' => $user->id, 'release_count' => 99]); $result = invokeGroupContributionHistory($user); expect($result)->toHaveCount(1) ->and($result[0]['group']['id'])->toBe($ownerGroup->id) ->and($result[0]['role'])->toBe(Group::ROLE_OWNER) ->and($result[0]['joined_at'])->toBeString(); }); it('keeps contribution-history query count bounded as group count grows', function (): void { $counts = []; foreach ([0, 1, 2, 4, 8] as $groupCount) { $user = User::factory()->create(); for ($index = 0; $index < $groupCount; $index++) { $group = Group::factory()->create([ 'slug' => 'query-count-group-' . $groupCount . '-' . $index . '-' . uniqid(), ]); GroupContributorStat::create([ 'group_id' => $group->id, 'user_id' => $user->id, 'credited_artworks_count' => $groupCount - $index, 'release_count' => $groupCount - $index, ]); } DB::flushQueryLog(); DB::enableQueryLog(); invokeGroupContributionHistory($user); $counts[$groupCount] = count(DB::getQueryLog()); DB::disableQueryLog(); } expect($counts)->toBe([ 0 => 1, 1 => 8, 2 => 8, 4 => 8, 8 => 8, ]); });