Allow heading tags (h1-h6) in ContentSanitizer so news editor headings render

This commit is contained in:
2026-06-04 07:52:57 +02:00
parent 0b33a1b074
commit 15870ddb1f
191 changed files with 15453 additions and 1786 deletions

View File

@@ -0,0 +1,148 @@
<?php
declare(strict_types=1);
use App\Models\EnhanceJob;
use App\Models\User;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
beforeEach(function (): void {
config()->set('enhance.disk', 'public');
config()->set('enhance.lifecycle.cleanup_chunk_size', 10);
Storage::fake('public');
});
it('does not delete files during cleanup dry run', function (): void {
$owner = User::factory()->create();
Storage::disk('public')->put('enhance/sources/1/source.png', UploadedFile::fake()->image('source.png')->get());
Storage::disk('public')->put('enhance/outputs/1/output.webp', UploadedFile::fake()->image('output.webp')->get());
Storage::disk('public')->put('enhance/previews/1/preview.webp', UploadedFile::fake()->image('preview.webp')->get());
$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' => 'enhance/sources/1/source.png',
'output_disk' => 'public',
'output_path' => 'enhance/outputs/1/output.webp',
'preview_disk' => 'public',
'preview_path' => 'enhance/previews/1/preview.webp',
'expires_at' => now()->subMinute(),
]);
$this->artisan('enhance:cleanup --dry-run')->assertSuccessful();
$job->refresh();
expect($job->status)->toBe(EnhanceJob::STATUS_COMPLETED);
Storage::disk('public')->assertExists('enhance/sources/1/source.png');
Storage::disk('public')->assertExists('enhance/outputs/1/output.webp');
Storage::disk('public')->assertExists('enhance/previews/1/preview.webp');
});
it('deletes expired completed job files in force mode', function (): void {
$owner = User::factory()->create();
Storage::disk('public')->put('enhance/sources/2/source.png', UploadedFile::fake()->image('source.png')->get());
Storage::disk('public')->put('enhance/outputs/2/output.webp', UploadedFile::fake()->image('output.webp')->get());
Storage::disk('public')->put('enhance/previews/2/preview.webp', UploadedFile::fake()->image('preview.webp')->get());
$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' => 'enhance/sources/2/source.png',
'output_disk' => 'public',
'output_path' => 'enhance/outputs/2/output.webp',
'preview_disk' => 'public',
'preview_path' => 'enhance/previews/2/preview.webp',
'expires_at' => now()->subMinute(),
]);
$this->artisan('enhance:cleanup --only=expired --force')->assertSuccessful();
$job->refresh();
expect($job->status)->toBe(EnhanceJob::STATUS_EXPIRED);
expect($job->source_path)->toBeNull();
expect($job->output_path)->toBeNull();
expect($job->preview_path)->toBeNull();
expect($job->metadata['cleanup']['reason'])->toBe('expired');
Storage::disk('public')->assertMissing('enhance/sources/2/source.png');
Storage::disk('public')->assertMissing('enhance/outputs/2/output.webp');
Storage::disk('public')->assertMissing('enhance/previews/2/preview.webp');
});
it('does not delete non enhance paths during cleanup', function (): void {
$owner = User::factory()->create();
Storage::disk('public')->put('uploads/artworks/unsafe.png', 'unsafe');
Storage::disk('public')->put('enhance/outputs/3/output.webp', UploadedFile::fake()->image('output.webp')->get());
$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' => 'uploads/artworks/unsafe.png',
'output_disk' => 'public',
'output_path' => 'enhance/outputs/3/output.webp',
'finished_at' => now()->subDays(10),
]);
$this->artisan('enhance:cleanup --only=failed --days=3 --force')->assertSuccessful();
$job->refresh();
expect($job->source_path)->toBe('uploads/artworks/unsafe.png');
expect($job->output_path)->toBeNull();
Storage::disk('public')->assertExists('uploads/artworks/unsafe.png');
Storage::disk('public')->assertMissing('enhance/outputs/3/output.webp');
});
it('cleans failed and soft deleted enhance files and records cleanup metadata', function (): void {
$owner = User::factory()->create();
Storage::disk('public')->put('enhance/sources/4/source.png', UploadedFile::fake()->image('source.png')->get());
$failed = 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/4/source.png',
'finished_at' => now()->subDays(10),
]);
Storage::disk('public')->put('enhance/sources/5/source.png', UploadedFile::fake()->image('source.png')->get());
$deleted = EnhanceJob::query()->create([
'user_id' => $owner->id,
'status' => EnhanceJob::STATUS_COMPLETED,
'engine' => EnhanceJob::ENGINE_STUB,
'mode' => 'standard',
'scale' => 2,
'source_disk' => 'public',
'source_path' => 'enhance/sources/5/source.png',
]);
$deleted->delete();
$deleted->forceFill(['deleted_at' => now()->subDays(5)])->saveQuietly();
$this->artisan('enhance:cleanup --only=failed --days=3 --force')->assertSuccessful();
$this->artisan('enhance:cleanup --only=deleted --days=3 --force')->assertSuccessful();
$failed->refresh();
$deleted = EnhanceJob::withTrashed()->findOrFail($deleted->id);
expect($failed->metadata['cleanup']['reason'])->toBe('failed-expired');
expect($deleted->metadata['cleanup']['reason'])->toBe('deleted-grace');
Storage::disk('public')->assertMissing('enhance/sources/4/source.png');
Storage::disk('public')->assertMissing('enhance/sources/5/source.png');
});