Files
AndyTranscribe/tests/Feature/RecordingDuplicateUploadTest.php
T
ben 34ccf0c32b Move recordings UI to Livewire pages with Flux components.
Replace controller-driven Blade views with full-page Livewire index/show/create flows so Flux tables, toasts, and uploads work natively.
2026-08-12 19:17:52 +02:00

131 lines
4.3 KiB
PHP

<?php
namespace Tests\Feature;
use App\Jobs\TranscribeRecording;
use App\Livewire\UploadRecordings;
use App\Models\Recording;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Storage;
use Livewire\Livewire;
use Tests\TestCase;
class RecordingDuplicateUploadTest extends TestCase
{
use RefreshDatabase;
protected User $user;
protected function setUp(): void
{
parent::setUp();
$this->user = User::factory()->create();
$this->actingAs($this->user);
}
public function test_duplicate_content_hash_is_skipped_on_upload(): void
{
Storage::fake('local');
Bus::fake();
$first = UploadedFile::fake()->createWithContent('meeting.mp3', 'identical-audio-bytes');
$duplicate = UploadedFile::fake()->createWithContent('meeting-copy.mp3', 'identical-audio-bytes');
Livewire::test(UploadRecordings::class)
->set('audio', [$first])
->assertRedirect();
$this->assertSame(1, Recording::query()->count());
Bus::assertDispatched(TranscribeRecording::class, 1);
Livewire::test(UploadRecordings::class)
->set('audio', [$duplicate])
->assertRedirect(route('recordings.create'))
->assertSessionHas('error');
$this->assertSame(1, Recording::query()->count());
Bus::assertDispatched(TranscribeRecording::class, 1);
}
public function test_batch_upload_skips_duplicate_content_within_request(): void
{
Storage::fake('local');
Bus::fake();
$one = UploadedFile::fake()->createWithContent('one.mp3', 'same-bytes');
$two = UploadedFile::fake()->createWithContent('two.mp3', 'same-bytes');
$three = UploadedFile::fake()->createWithContent('three.mp3', 'different-bytes');
Livewire::test(UploadRecordings::class)
->set('audio', [$one, $two, $three])
->assertRedirect(route('recordings.index'))
->assertSessionHas('success');
$this->assertStringContainsString('Skipped 1 duplicate', session('success'));
$this->assertSame(2, Recording::query()->count());
Bus::assertDispatched(TranscribeRecording::class, 2);
}
public function test_upload_page_mentions_duplicate_skipping(): void
{
Recording::query()->create([
'user_id' => $this->user->id,
'title' => 'Existing',
'original_filename' => 'note.mp3',
'file_path' => 'recordings/note.mp3',
'file_size_bytes' => 2048,
'content_hash' => str_repeat('a', 64),
'transcription_status' => 'done',
]);
$this->get(route('recordings.create'))
->assertOk()
->assertSeeLivewire('upload-recordings')
->assertSee('Duplicate files', false);
}
public function test_duplicate_filename_and_size_is_skipped_without_content_hash(): void
{
Storage::fake('local');
Bus::fake();
Recording::query()->create([
'user_id' => $this->user->id,
'title' => 'Legacy',
'original_filename' => 'legacy.mp3',
'file_path' => 'recordings/legacy.mp3',
'file_size_bytes' => strlen('legacy-audio'),
'content_hash' => null,
'transcription_status' => 'done',
]);
Livewire::test(UploadRecordings::class)
->set('audio', [UploadedFile::fake()->createWithContent('legacy.mp3', 'legacy-audio')])
->assertRedirect(route('recordings.create'))
->assertSessionHas('error');
$this->assertSame(1, Recording::query()->count());
Bus::assertNothingDispatched();
}
public function test_stored_recording_persists_content_hash(): void
{
Storage::fake('local');
Bus::fake();
$file = UploadedFile::fake()->createWithContent('hash-me.mp3', 'payload-for-hash');
Livewire::test(UploadRecordings::class)
->set('audio', [$file])
->assertRedirect();
$recording = Recording::query()->first();
$this->assertNotNull($recording);
$this->assertSame(hash('sha256', 'payload-for-hash'), $recording->content_hash);
}
}