Files
fotospiel-app/tests/Feature/LiveShowRealtimeTest.php
Codex Agent 3f3061a899
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled
Add live show docs and smoke tests
2026-01-05 19:42:58 +01:00

137 lines
4.5 KiB
PHP

<?php
namespace Tests\Feature;
use App\Enums\PhotoLiveStatus;
use App\Models\Event;
use App\Models\Photo;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class LiveShowRealtimeTest extends TestCase
{
use RefreshDatabase;
public function test_live_show_state_returns_ordered_photos_and_cursor(): void
{
$event = Event::factory()->create([
'live_show_token' => str_repeat('a', 64),
]);
$first = Photo::factory()->for($event)->create([
'status' => 'approved',
'live_status' => PhotoLiveStatus::APPROVED,
'live_approved_at' => now()->subMinutes(10),
]);
$second = Photo::factory()->for($event)->create([
'status' => 'approved',
'live_status' => PhotoLiveStatus::APPROVED,
'live_approved_at' => now()->subMinutes(3),
]);
$response = $this->getJson("/api/v1/live-show/{$event->live_show_token}");
$response->assertOk();
$response->assertJsonPath('photos.0.id', $first->id);
$response->assertJsonPath('photos.1.id', $second->id);
$response->assertJsonPath('cursor.id', $second->id);
$response->assertJsonStructure([
'settings',
'settings_version',
'photos',
'cursor' => ['approved_at', 'id'],
]);
}
public function test_live_show_updates_respects_cursor(): void
{
$event = Event::factory()->create([
'live_show_token' => str_repeat('b', 64),
]);
$first = Photo::factory()->for($event)->create([
'status' => 'approved',
'live_status' => PhotoLiveStatus::APPROVED,
'live_approved_at' => now()->subMinutes(9),
]);
$second = Photo::factory()->for($event)->create([
'status' => 'approved',
'live_status' => PhotoLiveStatus::APPROVED,
'live_approved_at' => now()->subMinutes(6),
]);
$third = Photo::factory()->for($event)->create([
'status' => 'approved',
'live_status' => PhotoLiveStatus::APPROVED,
'live_approved_at' => now()->subMinutes(1),
]);
$query = http_build_query([
'after_approved_at' => $second->live_approved_at->toAtomString(),
'after_id' => $second->id,
]);
$response = $this->getJson("/api/v1/live-show/{$event->live_show_token}/updates?{$query}");
$response->assertOk();
$response->assertJsonCount(1, 'photos');
$response->assertJsonPath('photos.0.id', $third->id);
$response->assertJsonPath('cursor.id', $third->id);
$response->assertJsonMissing(['photos' => [['id' => $first->id]]]);
}
public function test_live_show_returns_404_for_invalid_token(): void
{
$response = $this->getJson('/api/v1/live-show/invalid-token');
$response->assertNotFound();
}
public function test_live_show_updates_returns_settings_when_version_changes(): void
{
$event = Event::factory()->create([
'live_show_token' => str_repeat('c', 64),
'settings' => [
'live_show' => [
'effect_preset' => 'film_cut',
],
],
]);
$state = $this->getJson("/api/v1/live-show/{$event->live_show_token}");
$state->assertOk();
$version = $state->json('settings_version');
$updates = $this->getJson("/api/v1/live-show/{$event->live_show_token}/updates?settings_version={$version}");
$updates->assertOk();
$updates->assertJsonPath('settings', null);
$event->forceFill([
'settings' => [
'live_show' => [
'effect_preset' => 'shutter_flash',
],
],
])->save();
$updates = $this->getJson("/api/v1/live-show/{$event->live_show_token}/updates?settings_version={$version}");
$updates->assertOk();
$updates->assertJsonMissing(['settings' => null]);
$updates->assertJsonPath('settings.effect_preset', 'shutter_flash');
}
public function test_live_show_updates_rejects_invalid_cursor(): void
{
$event = Event::factory()->create([
'live_show_token' => str_repeat('d', 64),
]);
$response = $this->getJson("/api/v1/live-show/{$event->live_show_token}/updates?after_approved_at=invalid&after_id=1");
$response->assertStatus(422);
$response->assertJsonPath('error', 'invalid_cursor');
}
}