set('enhance.disk', 'public'); Storage::fake('public'); Queue::fake(); }); it('blocks regular users from moderation enhance write actions', function (): void { $user = User::factory()->create(); $owner = User::factory()->create(); $job = EnhanceJob::query()->create([ 'user_id' => $owner->id, 'status' => EnhanceJob::STATUS_FAILED, 'engine' => EnhanceJob::ENGINE_STUB, 'mode' => 'standard', 'scale' => 2, ]); $this->actingAs($user) ->post(route('admin.enhance.retry', ['enhanceJob' => $job])) ->assertForbidden(); $this->actingAs($user) ->post(route('admin.enhance.mark-failed', ['enhanceJob' => $job])) ->assertForbidden(); $this->actingAs($user) ->delete(route('admin.enhance.destroy', ['enhanceJob' => $job])) ->assertForbidden(); }); it('allows a moderator to retry a failed enhance job', function (): void { $moderator = User::factory()->create(['role' => 'moderator']); $owner = User::factory()->create(); Storage::disk('public')->put('enhance/sources/20/source.png', 'source'); $job = EnhanceJob::query()->create([ 'user_id' => $owner->id, 'status' => EnhanceJob::STATUS_FAILED, 'engine' => EnhanceJob::ENGINE_STUB, 'mode' => 'standard', 'scale' => 2, 'source_disk' => 'public', 'source_path' => 'enhance/sources/20/source.png', ]); $this->actingAs($moderator) ->post(route('admin.enhance.retry', ['enhanceJob' => $job])) ->assertRedirect(route('admin.enhance.show', ['enhanceJob' => $job])); $job->refresh(); expect($job->status)->toBe(EnhanceJob::STATUS_QUEUED); Queue::assertPushed(ProcessEnhanceJob::class); }); it('allows a moderator to mark a stuck processing job as failed', function (): void { $moderator = User::factory()->create(['role' => 'moderator']); $owner = User::factory()->create(); $job = EnhanceJob::query()->create([ 'user_id' => $owner->id, 'status' => EnhanceJob::STATUS_PROCESSING, 'engine' => EnhanceJob::ENGINE_STUB, 'mode' => 'standard', 'scale' => 2, 'started_at' => now()->subMinutes(40), ]); $this->actingAs($moderator) ->post(route('admin.enhance.mark-failed', ['enhanceJob' => $job])) ->assertRedirect(route('admin.enhance.show', ['enhanceJob' => $job])); $job->refresh(); expect($job->status)->toBe(EnhanceJob::STATUS_FAILED); expect($job->error_message)->toBe('Marked as failed by moderator.'); expect($job->metadata['moderation']['marked_failed_by'])->toBe($moderator->id); }); it('uses safe cleanup when moderation deletes a job', function (): void { $moderator = User::factory()->create(['role' => 'moderator']); $owner = User::factory()->create(); Storage::disk('public')->put('uploads/artworks/unsafe.png', 'unsafe'); Storage::disk('public')->put('enhance/outputs/21/output.webp', 'output'); $job = EnhanceJob::query()->create([ 'user_id' => $owner->id, 'status' => EnhanceJob::STATUS_COMPLETED, 'engine' => EnhanceJob::ENGINE_STUB, 'mode' => 'standard', 'scale' => 2, 'source_disk' => 'public', 'source_path' => 'uploads/artworks/unsafe.png', 'output_disk' => 'public', 'output_path' => 'enhance/outputs/21/output.webp', ]); $this->actingAs($moderator) ->delete(route('admin.enhance.destroy', ['enhanceJob' => $job])) ->assertRedirect(route('admin.enhance.index')); expect(EnhanceJob::withTrashed()->find($job->id)?->trashed())->toBeTrue(); Storage::disk('public')->assertExists('uploads/artworks/unsafe.png'); Storage::disk('public')->assertMissing('enhance/outputs/21/output.webp'); });