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-...).
This commit is contained in:
Thorsten Bus 2026-07-06 10:54:27 +02:00
parent 2a68d098a2
commit 27461b7c28
3 changed files with 112 additions and 38 deletions

View file

@ -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"
},

102
composer.lock generated
View file

@ -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,

View file

@ -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
{