new test files
This commit is contained in:
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
use App\Models\Artwork;
|
||||
use App\Models\User;
|
||||
use App\Models\World;
|
||||
use App\Models\WorldRewardGrant;
|
||||
use App\Models\WorldRelation;
|
||||
use App\Models\WorldSubmission;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
@@ -82,7 +83,7 @@ it('creates pending world submissions when publishing an artwork draft', functio
|
||||
'category' => $categoryId,
|
||||
'tags' => ['world', 'submission'],
|
||||
'world_submissions' => [
|
||||
['world_id' => $world->id, 'note' => 'Fits the active theme.'],
|
||||
['world_id' => $world->id, 'note' => 'Fits the active theme.', 'source_surface' => 'upload_flow'],
|
||||
],
|
||||
])
|
||||
->assertOk()
|
||||
@@ -96,6 +97,15 @@ it('creates pending world submissions when publishing an artwork draft', functio
|
||||
'is_featured' => false,
|
||||
'note' => 'Fits the active theme.',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('world_analytics_events', [
|
||||
'world_id' => $world->id,
|
||||
'event_type' => 'world_submission_created',
|
||||
'source_surface' => 'upload_flow',
|
||||
'entity_type' => 'artwork',
|
||||
'entity_id' => $artwork->id,
|
||||
'entity_title' => 'World Upload',
|
||||
]);
|
||||
});
|
||||
|
||||
it('creates live world participation immediately for auto-add worlds', function (): void {
|
||||
@@ -133,6 +143,14 @@ it('creates live world participation immediately for auto-add worlds', function
|
||||
'status' => WorldSubmission::STATUS_LIVE,
|
||||
'is_featured' => false,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('world_reward_grants', [
|
||||
'user_id' => $creator->id,
|
||||
'world_id' => $world->id,
|
||||
'artwork_id' => $artwork->id,
|
||||
'reward_type' => 'participant',
|
||||
'grant_source' => 'automatic',
|
||||
]);
|
||||
});
|
||||
|
||||
it('syncs world submissions from the studio artwork editor update flow', function (): void {
|
||||
@@ -319,7 +337,8 @@ it('shows and reviews world participation in the studio world editor', function
|
||||
->component('Studio/StudioWorldEditor')
|
||||
->where('world.participation_mode', World::PARTICIPATION_MODE_MANUAL_APPROVAL)
|
||||
->where('world.submission_review_queue.counts.pending', 1)
|
||||
->where('world.submission_review_queue.items.0.artwork.title', 'Queue Artwork'));
|
||||
->where('world.submission_review_queue.items.0.artwork.title', 'Queue Artwork')
|
||||
->where('world.submission_review_queue.items.0.can_grant_manual_rewards', false));
|
||||
|
||||
$this->actingAs($moderator)
|
||||
->post(route('studio.worlds.submissions.approve', ['world' => $world->id, 'submission' => $submission->id]))
|
||||
@@ -336,6 +355,20 @@ it('shows and reviews world participation in the studio world editor', function
|
||||
'reviewed_by_user_id' => $moderator->id,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('world_reward_grants', [
|
||||
'user_id' => $creator->id,
|
||||
'world_id' => $world->id,
|
||||
'reward_type' => 'participant',
|
||||
'grant_source' => 'automatic',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('world_reward_grants', [
|
||||
'user_id' => $creator->id,
|
||||
'world_id' => $world->id,
|
||||
'reward_type' => 'featured',
|
||||
'grant_source' => 'automatic',
|
||||
]);
|
||||
|
||||
$this->actingAs($moderator)
|
||||
->post(route('studio.worlds.submissions.block', ['world' => $world->id, 'submission' => $submission->id]), [
|
||||
'review_note' => 'Off brief for this world.',
|
||||
@@ -348,6 +381,114 @@ it('shows and reviews world participation in the studio world editor', function
|
||||
'moderation_reason' => 'Off brief for this world.',
|
||||
'is_featured' => false,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseMissing('world_reward_grants', [
|
||||
'user_id' => $creator->id,
|
||||
'world_id' => $world->id,
|
||||
'reward_type' => 'featured',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('world_reward_grants', [
|
||||
'user_id' => $creator->id,
|
||||
'world_id' => $world->id,
|
||||
'reward_type' => 'participant',
|
||||
'grant_source' => 'automatic',
|
||||
]);
|
||||
});
|
||||
|
||||
it('allows moderators to grant and revoke manual world rewards', function (): void {
|
||||
$moderator = User::factory()->create([
|
||||
'role' => 'moderator',
|
||||
'username' => 'worldrewardmod-' . Str::lower(Str::random(6)),
|
||||
]);
|
||||
$creator = User::factory()->create();
|
||||
$world = acceptingWorld($moderator);
|
||||
$artwork = Artwork::factory()->for($creator)->create([
|
||||
'title' => 'Reward Artwork',
|
||||
'slug' => 'reward-artwork',
|
||||
'artwork_status' => 'published',
|
||||
'published_at' => now()->subDay(),
|
||||
'is_public' => true,
|
||||
'visibility' => Artwork::VISIBILITY_PUBLIC,
|
||||
]);
|
||||
|
||||
$submission = WorldSubmission::query()->create([
|
||||
'world_id' => $world->id,
|
||||
'artwork_id' => $artwork->id,
|
||||
'submitted_by_user_id' => $creator->id,
|
||||
'status' => WorldSubmission::STATUS_LIVE,
|
||||
'reviewed_by_user_id' => $moderator->id,
|
||||
'reviewed_at' => now()->subHour(),
|
||||
]);
|
||||
|
||||
$this->actingAs($moderator)
|
||||
->post(route('studio.worlds.submissions.rewards.grant', ['world' => $world->id, 'submission' => $submission->id, 'rewardType' => 'winner']), [
|
||||
'review_note' => 'Editorial pick for the final showcase.',
|
||||
])
|
||||
->assertRedirect();
|
||||
|
||||
$grant = WorldRewardGrant::query()->where('user_id', $creator->id)->where('world_id', $world->id)->where('reward_type', 'winner')->first();
|
||||
|
||||
expect($grant)->not->toBeNull();
|
||||
|
||||
$this->assertDatabaseHas('notifications', [
|
||||
'type' => 'world_reward_granted',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('user_activities', [
|
||||
'user_id' => $creator->id,
|
||||
'type' => 'world_reward',
|
||||
'entity_type' => 'world_reward',
|
||||
'entity_id' => $grant->id,
|
||||
]);
|
||||
|
||||
$this->actingAs($moderator)
|
||||
->post(route('studio.worlds.submissions.rewards.revoke', ['world' => $world->id, 'submission' => $submission->id, 'rewardType' => 'winner']))
|
||||
->assertRedirect();
|
||||
|
||||
$this->assertDatabaseMissing('world_reward_grants', [
|
||||
'user_id' => $creator->id,
|
||||
'world_id' => $world->id,
|
||||
'reward_type' => 'winner',
|
||||
]);
|
||||
});
|
||||
|
||||
it('rejects manual world rewards for non-live submissions', function (): void {
|
||||
$moderator = User::factory()->create([
|
||||
'role' => 'moderator',
|
||||
'username' => 'worldrewardpending-' . Str::lower(Str::random(6)),
|
||||
]);
|
||||
$creator = User::factory()->create();
|
||||
$world = acceptingWorld($moderator);
|
||||
$artwork = Artwork::factory()->for($creator)->create([
|
||||
'title' => 'Pending Reward Artwork',
|
||||
'slug' => 'pending-reward-artwork',
|
||||
'artwork_status' => 'published',
|
||||
'published_at' => now()->subDay(),
|
||||
'is_public' => true,
|
||||
'visibility' => Artwork::VISIBILITY_PUBLIC,
|
||||
]);
|
||||
|
||||
$submission = WorldSubmission::query()->create([
|
||||
'world_id' => $world->id,
|
||||
'artwork_id' => $artwork->id,
|
||||
'submitted_by_user_id' => $creator->id,
|
||||
'status' => WorldSubmission::STATUS_PENDING,
|
||||
]);
|
||||
|
||||
$this->actingAs($moderator)
|
||||
->from(route('studio.worlds.edit', ['world' => $world->id]))
|
||||
->post(route('studio.worlds.submissions.rewards.grant', ['world' => $world->id, 'submission' => $submission->id, 'rewardType' => 'winner']), [
|
||||
'review_note' => 'Tried to award too early.',
|
||||
])
|
||||
->assertRedirect(route('studio.worlds.edit', ['world' => $world->id]))
|
||||
->assertSessionHasErrors(['submission']);
|
||||
|
||||
$this->assertDatabaseMissing('world_reward_grants', [
|
||||
'user_id' => $creator->id,
|
||||
'world_id' => $world->id,
|
||||
'reward_type' => 'winner',
|
||||
]);
|
||||
});
|
||||
|
||||
it('renders only live community submissions on public world pages and hides pending or blocked ones', function (): void {
|
||||
@@ -478,4 +619,72 @@ it('exposes world participation badges on the artwork page for curated and live
|
||||
return $items->count() === 1
|
||||
&& $items->contains(fn (array $item): bool => ($item['badge_label'] ?? null) === 'Featured in Retro Month');
|
||||
});
|
||||
});
|
||||
|
||||
it('prioritizes active campaign worlds in creator submission options', function (): void {
|
||||
$creator = User::factory()->create();
|
||||
|
||||
$liveCampaign = acceptingWorld(attributes: [
|
||||
'title' => 'Spring Vibes',
|
||||
'slug' => 'spring-vibes',
|
||||
'is_active_campaign' => true,
|
||||
'is_homepage_featured' => true,
|
||||
'campaign_priority' => 500,
|
||||
'campaign_label' => 'Live now',
|
||||
'teaser_title' => 'Now live: Spring Vibes',
|
||||
'teaser_summary' => 'Fresh spring palettes and active submissions.',
|
||||
'promotion_starts_at' => now()->subHour(),
|
||||
'promotion_ends_at' => now()->addDays(5),
|
||||
]);
|
||||
|
||||
$regularWorld = acceptingWorld(attributes: [
|
||||
'title' => 'Open Worlds Lab',
|
||||
'slug' => 'open-worlds-lab',
|
||||
'is_active_campaign' => false,
|
||||
'is_homepage_featured' => false,
|
||||
'campaign_priority' => null,
|
||||
]);
|
||||
|
||||
$options = app(\App\Services\Worlds\WorldSubmissionService::class)->eligibleWorldOptions($creator);
|
||||
|
||||
expect($options)->toHaveCount(2)
|
||||
->and($options[0]['id'])->toBe($liveCampaign->id)
|
||||
->and($options[0]['teaser_title'])->toBe('Now live: Spring Vibes')
|
||||
->and(collect($options[0]['status_badges'])->pluck('label')->all())->toContain('Live now', 'Featured')
|
||||
->and($options[1]['id'])->toBe($regularWorld->id);
|
||||
});
|
||||
|
||||
it('only exposes the canonical current edition for recurring submission options', function (): void {
|
||||
$creator = User::factory()->create();
|
||||
|
||||
acceptingWorld(attributes: [
|
||||
'title' => 'Pixel Week 2025',
|
||||
'slug' => 'pixel-week-2025',
|
||||
'is_recurring' => true,
|
||||
'recurrence_key' => 'pixel-week',
|
||||
'edition_year' => 2025,
|
||||
'is_active_campaign' => false,
|
||||
'is_homepage_featured' => false,
|
||||
'campaign_priority' => 50,
|
||||
'starts_at' => now()->subDays(30),
|
||||
'ends_at' => now()->addDays(2),
|
||||
]);
|
||||
|
||||
$currentEdition = acceptingWorld(attributes: [
|
||||
'title' => 'Pixel Week 2026',
|
||||
'slug' => 'pixel-week-2026',
|
||||
'is_recurring' => true,
|
||||
'recurrence_key' => 'pixel-week',
|
||||
'edition_year' => 2026,
|
||||
'is_active_campaign' => true,
|
||||
'is_homepage_featured' => true,
|
||||
'campaign_priority' => 500,
|
||||
'teaser_title' => 'Now live: Pixel Week 2026',
|
||||
]);
|
||||
|
||||
$options = app(\App\Services\Worlds\WorldSubmissionService::class)->eligibleWorldOptions($creator);
|
||||
|
||||
expect($options)->toHaveCount(1)
|
||||
->and($options[0]['id'])->toBe($currentEdition->id)
|
||||
->and($options[0]['title'])->toBe('Pixel Week 2026');
|
||||
});
|
||||
Reference in New Issue
Block a user