withoutVite(); $user = User::factory()->create(); Service::factory()->create([ 'date' => Carbon::today()->subDay(), 'finalized_at' => null, ]); $todayService = Service::factory()->create([ 'title' => 'Gottesdienst Heute', 'date' => Carbon::today(), 'finalized_at' => null, ]); $futureService = Service::factory()->create([ 'title' => 'Gottesdienst Zukunft', 'date' => Carbon::today()->addDays(3), 'finalized_at' => null, ]); $song = Song::factory()->create(); $arrangement = SongArrangement::factory()->create([ 'song_id' => $song->id, ]); ServiceSong::create([ 'service_id' => $todayService->id, 'song_id' => $song->id, 'song_arrangement_id' => $arrangement->id, 'use_translation' => false, 'order' => 1, 'cts_song_name' => 'Song 1', 'cts_ccli_id' => '100001', ]); ServiceSong::create([ 'service_id' => $todayService->id, 'song_id' => $song->id, 'song_arrangement_id' => null, 'use_translation' => false, 'order' => 2, 'cts_song_name' => 'Song 2', 'cts_ccli_id' => '100002', ]); ServiceSong::create([ 'service_id' => $todayService->id, 'song_id' => null, 'song_arrangement_id' => null, 'use_translation' => false, 'order' => 3, 'cts_song_name' => 'Song 3', 'cts_ccli_id' => '100003', ]); ServiceSong::create([ 'service_id' => $futureService->id, 'song_id' => $song->id, 'song_arrangement_id' => $arrangement->id, 'use_translation' => false, 'order' => 1, 'cts_song_name' => 'Song 4', 'cts_ccli_id' => '100004', ]); ServiceSong::create([ 'service_id' => $futureService->id, 'song_id' => null, 'song_arrangement_id' => null, 'use_translation' => false, 'order' => 2, 'cts_song_name' => 'Song 5', 'cts_ccli_id' => '100005', ]); Slide::factory()->create([ 'service_id' => $todayService->id, 'type' => 'sermon', 'expire_date' => null, ]); Slide::factory()->create([ 'service_id' => null, 'type' => 'information', 'expire_date' => Carbon::today()->addDay(), ]); Slide::factory()->create([ 'service_id' => null, 'type' => 'information', 'expire_date' => Carbon::today()->addDays(5), ]); Slide::factory()->create([ 'service_id' => $todayService->id, 'type' => 'information', 'expire_date' => Carbon::today()->addDays(10), ]); Slide::factory()->create([ 'service_id' => null, 'type' => 'information', 'expire_date' => Carbon::today()->subDay(), ]); $response = $this->actingAs($user)->get(route('services.index')); $response->assertOk(); $response->assertInertia( fn ($page) => $page ->component('Services/Index') ->has('services', 2) ->where('services.0.id', $todayService->id) ->where('services.0.title', 'Gottesdienst Heute') ->where('services.0.songs_total_count', 3) ->where('services.0.songs_mapped_count', 2) ->where('services.0.songs_arranged_count', 1) ->where('services.0.has_sermon_slides', true) ->where('services.0.info_slides_count', 3) ->where('services.1.id', $futureService->id) ->where('services.1.title', 'Gottesdienst Zukunft') ->where('services.1.songs_total_count', 2) ->where('services.1.songs_mapped_count', 1) ->where('services.1.songs_arranged_count', 1) ->where('services.1.has_sermon_slides', false) ->where('services.1.info_slides_count', 1) ); } public function test_service_kann_abgeschlossen_werden(): void { Carbon::setTestNow('2026-03-01 10:00:00'); $user = User::factory()->create(); $service = Service::factory()->create([ 'finalized_at' => null, ]); // Finalize with confirmed=true to skip prerequisite check $response = $this->actingAs($user)->postJson(route('services.finalize', $service), ['confirmed' => true]); $response->assertOk(); $response->assertJson(['needs_confirmation' => false, 'success' => 'Service wurde abgeschlossen.']); $this->assertSame(now()->toDateTimeString(), $service->fresh()->finalized_at?->toDateTimeString()); } public function test_service_kann_wieder_geoeffnet_werden(): void { $user = User::factory()->create(); $service = Service::factory()->create([ 'finalized_at' => now(), ]); $response = $this->actingAs($user)->post(route('services.reopen', $service)); $response->assertRedirect(route('services.index')); $this->assertNull($service->fresh()->finalized_at); } public function test_service_edit_seite_zeigt_service_mit_songs_und_slides(): void { Carbon::setTestNow('2026-03-01 10:00:00'); $this->withoutVite(); $user = User::factory()->create(); $service = Service::factory()->create([ 'title' => 'Gottesdienst', 'date' => Carbon::today()->addDays(7), 'preacher_name' => 'Pastor Mueller', 'finalized_at' => null, ]); $song = Song::factory()->create([ 'title' => 'Amazing Grace', 'ccli_id' => '4321', 'has_translation' => true, ]); $arrangement = SongArrangement::factory()->create([ 'song_id' => $song->id, 'name' => 'Normal', ]); ServiceSong::create([ 'service_id' => $service->id, 'song_id' => $song->id, 'song_arrangement_id' => $arrangement->id, 'use_translation' => true, 'order' => 1, 'cts_song_name' => 'Amazing Grace', 'cts_ccli_id' => '4321', ]); ServiceSong::create([ 'service_id' => $service->id, 'song_id' => null, 'song_arrangement_id' => null, 'use_translation' => false, 'order' => 2, 'cts_song_name' => 'Unbekannter Song', 'cts_ccli_id' => '9999', ]); Slide::factory()->create([ 'service_id' => $service->id, 'type' => 'sermon', ]); Slide::factory()->create([ 'service_id' => $service->id, 'type' => 'moderation', ]); Slide::factory()->create([ 'service_id' => null, 'type' => 'information', 'expire_date' => Carbon::today()->addDays(14), ]); $response = $this->actingAs($user)->get(route('services.edit', $service)); $response->assertOk(); $response->assertInertia( fn ($page) => $page ->component('Services/Edit') ->has('service') ->where('service.title', 'Gottesdienst') ->where('service.preacher_name', 'Pastor Mueller') ->has('serviceSongs', 2) ->where('serviceSongs.0.cts_song_name', 'Amazing Grace') ->where('serviceSongs.0.song.title', 'Amazing Grace') ->where('serviceSongs.0.song.has_translation', true) ->where('serviceSongs.0.arrangement.name', 'Normal') ->where('serviceSongs.1.cts_song_name', 'Unbekannter Song') ->where('serviceSongs.1.song', null) ->has('informationSlides', 1) ->has('moderationSlides', 1) ->has('sermonSlides', 1) ); } public function test_service_edit_erfordert_authentifizierung(): void { $service = Service::factory()->create(); $response = $this->get(route('services.edit', $service)); $response->assertRedirect(route('login')); } public function test_services_index_zeigt_nur_zukuenftige_services_standardmaessig(): void { Carbon::setTestNow('2026-03-01 10:00:00'); $this->withoutVite(); $user = User::factory()->create(); Service::factory()->create([ 'date' => Carbon::today()->subDays(5), 'title' => 'Vergangener Service', ]); $todayService = Service::factory()->create([ 'date' => Carbon::today(), 'title' => 'Heutiger Service', ]); $futureService = Service::factory()->create([ 'date' => Carbon::today()->addDays(3), 'title' => 'Zukünftiger Service', ]); $response = $this->actingAs($user)->get(route('services.index')); $response->assertOk(); $response->assertInertia( fn ($page) => $page ->component('Services/Index') ->has('services', 2) ->where('services.0.title', 'Heutiger Service') ->where('services.1.title', 'Zukünftiger Service') ->where('archived', false) ); } public function test_services_index_zeigt_vergangene_services_mit_archived_parameter(): void { Carbon::setTestNow('2026-03-01 10:00:00'); $this->withoutVite(); $user = User::factory()->create(); $pastService1 = Service::factory()->create([ 'date' => Carbon::today()->subDays(5), 'title' => 'Vergangener Service 1', ]); $pastService2 = Service::factory()->create([ 'date' => Carbon::today()->subDays(2), 'title' => 'Vergangener Service 2', ]); Service::factory()->create([ 'date' => Carbon::today(), 'title' => 'Heutiger Service', ]); Service::factory()->create([ 'date' => Carbon::today()->addDays(3), 'title' => 'Zukünftiger Service', ]); $response = $this->actingAs($user)->get(route('services.index', ['archived' => 1])); $response->assertOk(); $response->assertInertia( fn ($page) => $page ->component('Services/Index') ->has('services', 2) ->where('services.0.title', 'Vergangener Service 2') ->where('services.1.title', 'Vergangener Service 1') ->where('archived', true) ); } }