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(); } }