Improve recordings list sorting and live show-page status updates.

Add sortable columns with a fixed status width, and keep the show page in sync via Echo, polling, and Alpine hydrate while transcription runs.
This commit is contained in:
ben
2026-08-12 21:27:03 +02:00
parent 5f0f61995c
commit 8a66cf6f63
7 changed files with 344 additions and 67 deletions
+58 -3
View File
@@ -125,8 +125,8 @@ class IndexTest extends TestCase
Livewire::test(Index::class)
->assertSee('wire:poll', false)
->assertSee('Transcribing locally…')
->assertSee('40%')
->assertSee('Transcribing')
->assertDontSee('Transcribing locally…')
->assertSeeHtml('bg-amber-400');
}
@@ -151,7 +151,7 @@ class IndexTest extends TestCase
Livewire::test(Index::class)
->assertSee('Waiting in line')
->assertSee('Queued')
->assertSee('Queued — waiting to start…')
->assertDontSee('Queued — waiting to start…')
->assertDontSee('5%')
->assertSeeHtml('bg-zinc-400/15')
->assertDontSeeHtml('bg-amber-400');
@@ -282,4 +282,59 @@ class IndexTest extends TestCase
$this->assertDatabaseHas('recordings', ['id' => $recording->id]);
}
public function test_recordings_can_be_sorted_by_title(): void
{
$user = User::factory()->create();
$this->actingAs($user);
Recording::query()->create([
'user_id' => $user->id,
'title' => 'Zebra',
'original_filename' => 'z.mp3',
'file_path' => 'recordings/z.mp3',
'file_size_bytes' => 100,
'transcription_status' => 'done',
'created_at' => now()->subDay(),
]);
Recording::query()->create([
'user_id' => $user->id,
'title' => 'Alpha',
'original_filename' => 'a.mp3',
'file_path' => 'recordings/a.mp3',
'file_size_bytes' => 100,
'transcription_status' => 'done',
'created_at' => now(),
]);
Livewire::test(Index::class)
->call('sort', 'title')
->assertSet('sortBy', 'title')
->assertSet('sortDirection', 'asc')
->assertSeeInOrder(['Alpha', 'Zebra'])
->call('sort', 'title')
->assertSet('sortDirection', 'desc')
->assertSeeInOrder(['Zebra', 'Alpha']);
}
public function test_invalid_sort_column_is_ignored(): void
{
$user = User::factory()->create();
$this->actingAs($user);
Recording::query()->create([
'user_id' => $user->id,
'title' => 'Only one',
'original_filename' => 'one.mp3',
'file_path' => 'recordings/one.mp3',
'file_size_bytes' => 100,
'transcription_status' => 'done',
]);
Livewire::test(Index::class)
->call('sort', 'not_a_column')
->assertSet('sortBy', 'uploaded')
->assertSet('sortDirection', 'desc');
}
}
+77
View File
@@ -59,4 +59,81 @@ class ShowTest extends TestCase
$this->assertDatabaseMissing('recordings', ['id' => $recording->id]);
}
public function test_show_polls_while_transcription_is_active(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$recording = Recording::query()->create([
'user_id' => $user->id,
'title' => 'In progress',
'original_filename' => 'active.mp3',
'file_path' => 'recordings/active.mp3',
'file_size_bytes' => 100,
'transcription_status' => 'processing',
'transcription_progress' => 'Queued — waiting to start…',
'transcription_percent' => null,
'transcription_driver' => 'local',
'transcription_started_at' => now(),
]);
Livewire::test(Show::class, ['recording' => $recording])
->assertSee('wire:poll', false)
->assertSee('Queued — waiting to start…');
}
public function test_show_does_not_poll_when_transcription_is_idle(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$recording = Recording::query()->create([
'user_id' => $user->id,
'title' => 'Finished',
'original_filename' => 'done.mp3',
'file_path' => 'recordings/done.mp3',
'file_size_bytes' => 100,
'transcription_status' => 'done',
'transcript' => 'all done',
]);
Livewire::test(Show::class, ['recording' => $recording])
->assertDontSee('wire:poll', false);
}
public function test_show_refreshes_recording_on_transcription_broadcast(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$recording = Recording::query()->create([
'user_id' => $user->id,
'title' => 'Live update',
'original_filename' => 'live.mp3',
'file_path' => 'recordings/live.mp3',
'file_size_bytes' => 100,
'transcription_status' => 'pending',
'transcription_progress' => 'Queued — waiting to start…',
'transcription_driver' => 'local',
'transcription_started_at' => now(),
]);
$component = Livewire::test(Show::class, ['recording' => $recording]);
$recording->update([
'transcription_status' => 'processing',
'transcription_progress' => 'Transcribing locally…',
'transcription_percent' => 40,
]);
$component
->call('onTranscriptionUpdated', [
'id' => $recording->id,
'status' => 'processing',
])
->assertSet('recording.transcription_status', 'processing')
->assertSet('recording.transcription_percent', 40)
->assertSee('Transcribing locally…');
}
}