From 27461b7c288c73d2f08a5bbb2bbf286919888a08 Mon Sep 17 00:00:00 2001 From: Thorsten Bus Date: Mon, 6 Jul 2026 10:54:27 +0200 Subject: [PATCH] test: assert Abspann loop + dissolve on live parser Bump the propresenter parser to dev-master (20fe32a), which brings the background-layer and nametag-subtitle features onto the consumed bussnet/propresenter7-php-api branch and resolves the Slide::hasBackgroundMedia() regression. Strengthen AbspannExportTest to assert the now-live 10s auto-advance loop (completion AFTER_TIME == 10, target FIRST) and the Dissolve transition (renderId EC52A828-...). --- composer.json | 2 +- composer.lock | 102 ++++++++++++++++++++-------- tests/Feature/AbspannExportTest.php | 46 ++++++++++--- 3 files changed, 112 insertions(+), 38 deletions(-) diff --git a/composer.json b/composer.json index bdd89c7..b52cd46 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "laravel/sanctum": "^4.0", "laravel/socialite": "^5.24", "laravel/tinker": "^2.10.1", - "propresenter/parser": "dev-master", + "bussnet/propresenter7-php-api": "dev-master", "spatie/pdf-to-image": "^1.2", "tightenco/ziggy": "^2.0" }, diff --git a/composer.lock b/composer.lock index 8fd500b..1727c0d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "87837501106e784aa10ddd7743056cba", + "content-hash": "9bcdfde764499725d2469055e3a0e474", "packages": [ { "name": "5pm-hdh/churchtools-api", @@ -191,6 +191,77 @@ ], "time": "2026-02-10T14:33:43+00:00" }, + { + "name": "bussnet/propresenter7-php-api", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://git.stadtmission-butzbach.de/public/propresenter-php.git", + "reference": "20fe32af527b0d338e9921ffd17107000a8128c8" + }, + "require": { + "google/protobuf": "^4.0", + "php": "^8.4" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "default-branch": true, + "bin": [ + "bin/parse-song.php", + "bin/parse-playlist.php" + ], + "type": "library", + "autoload": { + "psr-4": { + "ProPresenter\\Parser\\": "src/", + "Rv\\Data\\": "generated/Rv/Data/", + "GPBMetadata\\": "generated/GPBMetadata/" + } + }, + "autoload-dev": { + "psr-4": { + "ProPresenter\\Parser\\Tests\\": "tests/" + } + }, + "scripts": { + "test": [ + "phpunit" + ], + "test:coverage": [ + "phpunit --coverage-text" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Thorsten Buss", + "role": "Developer" + } + ], + "description": "PHP library to read, modify, and generate ProPresenter 7 files (.pro songs, .proplaylist, .probundle, themes, and global library files).", + "homepage": "https://github.com/bussnet/propresenter7-php-api", + "keywords": [ + "ccli", + "church", + "parser", + "presentation", + "pro-file", + "probundle", + "proplaylist", + "propresenter", + "propresenter7", + "protobuf", + "worship" + ], + "support": { + "issues": "https://github.com/bussnet/propresenter7-php-api/issues", + "source": "https://github.com/bussnet/propresenter7-php-api" + }, + "time": "2026-06-21T07:58:24+00:00" + }, { "name": "carbonphp/carbon-doctrine-types", "version": "3.2.0", @@ -3813,33 +3884,6 @@ ], "time": "2026-01-27T09:17:28+00:00" }, - { - "name": "propresenter/parser", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://git.stadtmission-butzbach.de/public/propresenter-php.git", - "reference": "9e3e719806d8db3941444b8424fdd56b3b534aa8" - }, - "require": { - "google/protobuf": "^4.0", - "php": "^8.4" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "ProPresenter\\Parser\\": "src/", - "Rv\\Data\\": "generated/Rv/Data/", - "GPBMetadata\\": "generated/GPBMetadata/" - } - }, - "description": "ProPresenter song file parser", - "time": "2026-05-03T19:40:09+00:00" - }, { "name": "psr/clock", "version": "1.0.0", @@ -10862,7 +10906,7 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { - "propresenter/parser": 20 + "bussnet/propresenter7-php-api": 20 }, "prefer-stable": true, "prefer-lowest": false, diff --git a/tests/Feature/AbspannExportTest.php b/tests/Feature/AbspannExportTest.php index 934454d..065f883 100644 --- a/tests/Feature/AbspannExportTest.php +++ b/tests/Feature/AbspannExportTest.php @@ -14,6 +14,8 @@ use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\Storage; use ProPresenter\Parser\ProPlaylistReader; +use Rv\Data\Cue\CompletionActionType; +use Rv\Data\Cue\CompletionTargetType; use Tests\TestCase; final class AbspannExportTest extends TestCase @@ -66,18 +68,46 @@ public function test_abspann_is_last_item_with_keyvisual_first_then_information_ $this->assertTrue($slides[2]->hasMedia()); $this->assertSame('info2.jpg', $slides[2]->getLabel()); + // The Abspann is a self-advancing loop on the live parser round-trip: every cue + // auto-advances after 10s and the last cue jumps back to the first ("auto repeat all"). + $presentation = $abspann->getPresentation(); + $cues = $presentation->getCues(); + $this->assertCount(3, $cues); + + foreach ($cues as $cue) { + $this->assertSame( + CompletionActionType::COMPLETION_ACTION_TYPE_AFTER_TIME, + $cue->getCompletionActionType(), + 'Every Abspann cue must auto-advance after a fixed time', + ); + $this->assertSame(10.0, $cue->getCompletionTime(), 'Auto-advance must fire after 10 seconds'); + } + + // Leading cues step to the next slide; the final cue loops back to the first. + $this->assertSame(CompletionTargetType::COMPLETION_TARGET_TYPE_NEXT, $cues[0]->getCompletionTargetType()); + $this->assertSame(CompletionTargetType::COMPLETION_TARGET_TYPE_NEXT, $cues[1]->getCompletionTargetType()); + $this->assertSame( + CompletionTargetType::COMPLETION_TARGET_TYPE_FIRST, + $cues[count($cues) - 1]->getCompletionTargetType(), + 'The final Abspann cue must loop back to the first cue', + ); + + // The presentation carries the Dissolve transition (soft cross-fade between slides). + $this->assertTrue($presentation->hasTransition(), 'Abspann must use a slide transition'); + $effect = $presentation->getTransition()->getEffect(); + $this->assertNotNull($effect); + $this->assertSame('EC52A828-AD85-4602-B70C-1DEE7C904DB6', $effect->getRenderId()); + $this->assertSame('Dissolve', $effect->getName()); + $this->assertSame('Dissolves', $effect->getCategory()); + $this->cleanupTempDir($result['temp_dir']); } /** - * Auto-advance (10s), loop-to-first and the Dissolve transition are emitted into - * the slideData by addAbspannPresentation and are covered by the parser repo's - * in-memory ProFileGeneratorCompletionTest. They are intentionally NOT asserted - * here: the parser's generated protobuf descriptor does not (yet) register the - * Cue.completion_* and Presentation.transition fields, so serializeToString() - * drops them on the disk round-trip that every export performs. Once the parser - * stubs are regenerated these become observable on the exported .proplaylist and - * this note can be replaced with real assertions. + * Auto-advance (10s), loop-to-first and the Dissolve transition survive the disk + * round-trip and are asserted in + * test_abspann_is_last_item_with_keyvisual_first_then_information_slides. This test + * stays focused on the per-cue Abspann macro assignment. */ public function test_abspann_cues_carry_configured_abspann_macro(): void {