PASS Tests\Unit\ExampleTest ✓ that true is true PASS Tests\Feature\ApiLogControllerTest ✓ api log index zeigt die api logs seite mit paginated logs 0.14s ✓ api log index filtert nach suche 0.02s ✓ api log index filtert nach status 0.01s ✓ api request log scopes funktionieren 0.01s PASS Tests\Feature\ArrangementControllerTest ✓ create arrangement clones groups from default arrangement 0.02s ✓ clone arrangement duplicates current arrangement groups 0.01s ✓ update arrangement reorders and persists groups 0.01s ✓ cannot delete the last arrangement of a song 0.01s PASS Tests\Feature\ChurchToolsSyncTest ✓ cts:sync synchronisiert services, agenda songs und schreibt sync lo… 0.02s PASS Tests\Feature\CtsApiSpikeTest ✓ it syncs mocked future events and song shape through the CTS pipeli… 0.02s ✓ it returns auth blocker when API token is missing 0.01s PASS Tests\Feature\DatabaseSchemaTest ✓ all expected database tables exist 0.01s ✓ all factories create valid records 0.01s PASS Tests\Feature\ExampleTest ✓ example 0.01s PASS Tests\Feature\FileConversionTest ✓ convert image creates 1920x1080 jpg with black bars and thumbnail 0.11s ✓ portrait image gets pillarbox bars on left and right 0.18s PASS Tests\Feature\FinalizationTest ✓ finalize ohne voraussetzungen gibt warnungen zurueck 0.01s ✓ finalize mit confirmed=true trotz warnungen finalisiert service 0.01s ✓ finalize ohne warnungen finalisiert direkt 0.01s ✓ finalize warnt bei fehlenden song-zuordnungen 0.01s ✓ finalize warnt bei fehlenden predigtfolien 0.01s ✓ reopen setzt finalized_at zurueck 0.01s ✓ download gibt placeholder nachricht zurueck 0.01s ✓ finalize erfordert authentifizierung 0.01s ✓ download erfordert authentifizierung 0.01s ✓ service model isReadyToFinalize accessor 0.01s ✓ finalization status mit service ohne songs warnt nur bei predigtfol… 0.01s PASS Tests\Feature\HomeTest ✓ home route redirects unauthenticated users to login 0.01s ✓ home route redirects authenticated users to dashboard 0.01s PASS Tests\Feature\InformationBlockTest ✓ information slides shown dynamically by expire date 0.01s ✓ information slides expire on service date are still shown 0.01s ✓ information slides are global and appear in all services where not… 0.01s ✓ soft deleted information slides are not shown 0.01s ✓ information slides do not include moderation or sermon slides 0.01s ✓ information slides without expire_date are not shown 0.01s ✓ information slides ordered by uploaded_at descending 0.01s PASS Tests\Feature\MissingSongMailTest ✓ missing song request mailable renders with german content 0.02s ✓ missing song request mailable has correct subject 0.01s PASS Tests\Feature\ModerationBlockTest ✓ moderation slides are service-specific 0.01s ✓ moderation slides do not include information slides 0.01s ✓ moderation slides require service_id 0.01s ✓ moderation block filters slides correctly 0.01s ✓ moderation slides do not have expire_date field 0.01s PASS Tests\Feature\OAuthTest ✓ it redirects unauthenticated users to login 0.01s ✓ it shows login page with OAuth button 0.01s ✓ it login page has no email or password inputs 0.01s ✓ it redirects to ChurchTools OAuth on auth initiation 0.01s ✓ it creates a new user from OAuth callback 0.01s ✓ it updates existing user on OAuth callback 0.01s ✓ it logs out user and redirects to login 0.01s ✓ it does not have register routes 0.01s ✓ it authenticated user can access dashboard 0.01s PASS Tests\Feature\ProPlaceholderTest ✓ Pro File Placeholder Endpoints → POST /api/songs/import-pro → it re… 0.01s ✓ Pro File Placeholder Endpoints → POST /api/songs/import-pro → it re… 0.01s ✓ Pro File Placeholder Endpoints → GET /api/songs/{song}/download-pro… 0.01s ✓ Pro File Placeholder Endpoints → GET /api/songs/{song}/download-pro… 0.01s ✓ Pro File Placeholder Endpoints → GET /api/songs/{song}/download-pro… 0.01s PASS Tests\Feature\SermonBlockTest ✓ sermon slides are service-specific 0.01s ✓ sermon slides do not include information slides 0.01s ✓ sermon slides require service_id 0.01s ✓ sermon block filters slides correctly 0.01s ✓ sermon slides do not have expire_date field 0.01s PASS Tests\Feature\ServiceControllerTest ✓ services index zeigt nur heutige und kuenftige services mit statusd… 0.02s ✓ service kann abgeschlossen werden 0.01s ✓ service kann wieder geoeffnet werden 0.01s ✓ service edit seite zeigt service mit songs und slides 0.01s ✓ service edit erfordert authentifizierung 0.01s ✓ services index zeigt nur zukuenftige services standardmaessig 0.01s ✓ services index zeigt vergangene services mit archived parameter 0.01s PASS Tests\Feature\SharedPropsTest ✓ shared props include auth user with expected fields when authentica… 0.01s ✓ shared props include null auth user when not logged in 0.01s ✓ shared props include flash success message 0.01s ✓ shared props include flash error message 0.01s ✓ shared props include last_synced_at from latest sync log 0.01s ✓ shared props include null last_synced_at when no sync log exists 0.01s ✓ shared props include app_name from config 0.01s PASS Tests\Feature\SlideControllerTest ✓ upload image creates slide with 1920x1080 jpg 0.10s ✓ upload image with expire_date stores date on slide 0.08s ✓ upload moderation slide without service_id fails 0.01s ✓ upload information slide without service_id is allowed 0.08s ✓ upload rejects unsupported file types 0.01s ✓ upload rejects invalid type 0.02s ✓ upload pptx dispatches conversion job 0.01s ✓ upload zip processes contained images 0.08s ✓ unauthenticated user cannot upload slides 0.01s ✓ delete slide soft deletes it 0.01s ✓ delete non-existing slide returns 404 0.01s ✓ update expire date on information slide 0.01s ✓ update expire date rejects non-information slides 0.01s ✓ expire date must be a valid date 0.03s ✓ expire date can be set to null 0.02s PASS Tests\Feature\SongControllerTest ✓ songs index returns paginated list 0.01s ✓ songs index excludes soft-deleted songs 0.01s ✓ songs index search by title 0.01s ✓ songs index search by ccli id 0.01s ✓ songs index requires authentication 0.01s ✓ store creates song with default groups and arrangement 0.02s ✓ store validates required title 0.02s ✓ store validates unique ccli_id 0.01s ✓ store allows null ccli_id 0.01s ✓ show returns song with groups slides and arrangements 0.01s ✓ show returns 404 for nonexistent song 0.01s ✓ show returns 404 for soft-deleted song 0.01s ✓ update modifies song metadata 0.01s ✓ update validates unique ccli_id excluding self 0.01s ✓ update allows keeping own ccli_id 0.01s ✓ destroy soft-deletes a song 0.01s ✓ destroy returns 404 for nonexistent song 0.01s ✓ last_used_in_service returns correct date from service_songs 0.01s ✓ last_used_in_service returns null when never used 0.01s ✓ duplicate arrangement clones arrangement with groups 0.01s PASS Tests\Feature\SongEditModalTest ✓ show returns song with full detail for modal 0.01s ✓ update saves title via auto-save 0.01s ✓ update saves ccli_id via auto-save 0.01s ✓ update saves copyright_text via auto-save 0.01s ✓ update can clear optional fields with null 0.01s ✓ update returns full song detail with arrangements 0.01s ✓ update validates title is required 0.01s ✓ update validates unique ccli_id against other songs 0.01s ✓ update requires authentication 0.01s ✓ show returns 404 for soft-deleted song 0.01s ✓ update returns 404 for nonexistent song 0.01s PASS Tests\Feature\SongIndexTest ✓ songs index page renders for authenticated users 0.01s ✓ songs index page redirects unauthenticated users to login 0.01s ✓ songs index route is named songs.index 0.01s ✓ songs api returns data for songs page 0.01s ✓ songs api search filters by title 0.01s ✓ songs api search filters by ccli id 0.01s ✓ songs api does not return soft-deleted songs 0.01s ✓ songs api paginates results 0.01s ✓ songs api delete soft-deletes a song 0.01s PASS Tests\Feature\SongMatchingTest ✓ autoMatch ordnet Song per CCLI-ID zu 0.01s ✓ autoMatch gibt false zurück wenn kein CCLI-ID vorhanden 0.01s ✓ autoMatch gibt false zurück wenn kein passender Song in DB 0.01s ✓ autoMatch überspringt bereits zugeordnete Songs 0.01s ✓ manualAssign ordnet Song manuell zu 0.01s ✓ manualAssign überschreibt bestehende Zuordnung 0.01s ✓ requestCreation sendet E-Mail und setzt request_sent_at 0.01s ✓ unassign entfernt Zuordnung 0.01s ✓ POST /api/service-songs/{id}/assign ordnet Song zu 0.01s ✓ POST /api/service-songs/{id}/assign validiert song_id 0.01s ✓ POST /api/service-songs/{id}/request sendet Anfrage-E-Mail 0.01s ✓ POST /api/service-songs/{id}/unassign entfernt Zuordnung 0.01s ✓ API Endpunkte erfordern Authentifizierung 0.01s ✓ API gibt 404 für nicht existierende ServiceSong 0.02s PASS Tests\Feature\SongPdfTest ✓ song pdf download returns pdf with correct content type 0.23s ✓ song pdf contains song title in filename 0.13s ✓ song pdf includes arrangement groups in order 0.14s ✓ song pdf includes translated text when present 0.19s ✓ song pdf includes copyright footer 0.13s ✓ song pdf returns 404 when arrangement does not belong to song 0.01s ✓ song pdf requires authentication 0.01s ✓ song pdf handles german umlauts correctly 0.18s ✓ song pdf works with empty arrangement (no groups) 0.13s ✓ song preview returns json with groups in arrangement order 0.01s ✓ song preview includes translation text when slides have translation… 0.01s ✓ song preview returns 404 when arrangement does not belong to song 0.01s ✓ song preview requires authentication 0.01s PASS Tests\Feature\SongsBlockTest ✓ songs block shows unmatched song with matching options 0.02s ✓ songs block provides matched song data for arrangement configurator… 0.01s PASS Tests\Feature\SyncControllerTest ✓ sync controller propagiert Fehlermeldung bei Sync-Fehler 0.01s ✓ sync controller zeigt Erfolgsmeldung bei erfolgreichem Sync 0.01s PASS Tests\Feature\TranslatePageTest ✓ translate page response contains ordered groups and slides 0.01s PASS Tests\Feature\TranslationServiceTest ✓ fetchFromUrl returns text from successful HTTP response 0.02s ✓ fetchFromUrl returns null on HTTP failure 0.01s ✓ fetchFromUrl returns null on connection error 0.01s ✓ fetchFromUrl returns null for empty response body 0.01s ✓ importTranslation distributes lines by slide line counts 0.01s ✓ importTranslation distributes across multiple groups 0.01s ✓ importTranslation handles fewer translation lines than original 0.01s ✓ importTranslation marks song as translated 0.01s ✓ markAsTranslated sets has_translation to true 0.01s ✓ removeTranslation clears all translated text and sets flag to false 0.01s ✓ POST translation/fetch-url returns scraped text 0.01s ✓ POST translation/fetch-url returns error on failure 0.01s ✓ POST translation/fetch-url validates url field 0.01s ✓ POST songs/{song}/translation/import distributes and saves translat… 0.01s ✓ POST songs/{song}/translation/import validates text field 0.01s ✓ POST songs/{song}/translation/import returns 404 for missing song 0.01s ✓ DELETE songs/{song}/translation removes translation 0.01s ✓ translation endpoints require authentication 0.01s Tests: 182 passed (999 assertions) Duration: 3.59s