tmpDir = sys_get_temp_dir() . '/propresenter-generator-test-' . uniqid(); mkdir($this->tmpDir, 0777, true); } protected function tearDown(): void { if (!is_dir($this->tmpDir)) { return; } foreach (scandir($this->tmpDir) ?: [] as $entry) { if ($entry === '.' || $entry === '..') { continue; } @unlink($this->tmpDir . '/' . $entry); } @rmdir($this->tmpDir); } #[Test] public function testGenerateCreatesValidSong(): void { $song = ProFileGenerator::generate( 'Simple Song', [ [ 'name' => 'Verse 1', 'color' => [0.1, 0.2, 0.3, 1.0], 'slides' => [ ['text' => 'Hello World'], ], ], ], [ ['name' => 'normal', 'groupNames' => ['Verse 1']], ], ); $this->assertSame('Simple Song', $song->getName()); $this->assertCount(1, $song->getGroups()); $this->assertCount(1, $song->getSlides()); $this->assertSame('Hello World', $song->getSlides()[0]->getPlainText()); $arrangement = $song->getArrangementByName('normal'); $this->assertNotNull($arrangement); $groups = $song->getGroupsForArrangement($arrangement); $this->assertCount(1, $groups); $this->assertSame('Verse 1', $groups[0]->getName()); } #[Test] public function testGenerateWithMultipleGroupsAndArrangements(): void { $song = ProFileGenerator::generate( 'Multi Song', [ [ 'name' => 'Verse 1', 'color' => [0.1, 0.2, 0.3, 1.0], 'slides' => [ ['text' => 'V1.1'], ['text' => 'V1.2'], ], ], [ 'name' => 'Chorus', 'color' => [0.4, 0.5, 0.6, 1.0], 'slides' => [ ['text' => 'C1'], ], ], ], [ ['name' => 'normal', 'groupNames' => ['Verse 1', 'Chorus']], ['name' => 'short', 'groupNames' => ['Chorus']], ], ); $this->assertSame(['Verse 1', 'Chorus'], array_map(fn ($group) => $group->getName(), $song->getGroups())); $verse1 = $song->getGroupByName('Verse 1'); $this->assertNotNull($verse1); $verseSlides = $song->getSlidesForGroup($verse1); $this->assertSame(['V1.1', 'V1.2'], array_map(fn ($slide) => $slide->getPlainText(), $verseSlides)); $chorus = $song->getGroupByName('Chorus'); $this->assertNotNull($chorus); $chorusSlides = $song->getSlidesForGroup($chorus); $this->assertSame(['C1'], array_map(fn ($slide) => $slide->getPlainText(), $chorusSlides)); $normal = $song->getArrangementByName('normal'); $this->assertNotNull($normal); $this->assertSame( ['Verse 1', 'Chorus'], array_map(fn ($group) => $group->getName(), $song->getGroupsForArrangement($normal)), ); $short = $song->getArrangementByName('short'); $this->assertNotNull($short); $this->assertSame( ['Chorus'], array_map(fn ($group) => $group->getName(), $song->getGroupsForArrangement($short)), ); } #[Test] public function testGenerateWithTranslation(): void { $song = ProFileGenerator::generate( 'Translation Song', [ [ 'name' => 'Verse 1', 'color' => [0.1, 0.2, 0.3, 1.0], 'slides' => [ ['text' => 'Original', 'translation' => 'Translated'], ], ], ], [ ['name' => 'normal', 'groupNames' => ['Verse 1']], ], ); $slide = $song->getSlides()[0]; $this->assertTrue($slide->hasTranslation()); $this->assertSame('Translated', $slide->getTranslation()?->getPlainText()); } #[Test] public function testGenerateWithCcliMetadata(): void { $song = ProFileGenerator::generate( 'CCLI Song', [ [ 'name' => 'Verse 1', 'color' => [0.1, 0.2, 0.3, 1.0], 'slides' => [ ['text' => 'Line'], ], ], ], [ ['name' => 'normal', 'groupNames' => ['Verse 1']], ], [ 'author' => 'Author Name', 'song_title' => 'Song Title', 'publisher' => 'Publisher Name', 'copyright_year' => 2024, 'song_number' => 12345, 'display' => true, 'artist_credits' => 'Artist Credits', 'album' => 'Album Name', ], ); $this->assertSame('Author Name', $song->getCcliAuthor()); $this->assertSame('Song Title', $song->getCcliSongTitle()); $this->assertSame('Publisher Name', $song->getCcliPublisher()); $this->assertSame(2024, $song->getCcliCopyrightYear()); $this->assertSame(12345, $song->getCcliSongNumber()); $this->assertTrue($song->getCcliDisplay()); $this->assertSame('Artist Credits', $song->getCcliArtistCredits()); $this->assertSame('Album Name', $song->getCcliAlbum()); } #[Test] public function testRoundTripFromTestPro(): void { $original = ProFileReader::read('/Users/thorsten/AI/propresenter/ref/Test.pro'); $groups = []; foreach ($original->getGroups() as $group) { $color = $group->getColor(); $slides = []; foreach ($original->getSlidesForGroup($group) as $slide) { $slides[] = [ 'text' => $slide->getPlainText(), 'translation' => $slide->hasTranslation() ? $slide->getTranslation()?->getPlainText() : null, ]; } $groups[] = [ 'name' => $group->getName(), 'color' => [ $color['r'] ?? 0.0, $color['g'] ?? 0.0, $color['b'] ?? 0.0, $color['a'] ?? 1.0, ], 'slides' => $slides, ]; } $arrangements = []; foreach ($original->getArrangements() as $arrangement) { $arrangements[] = [ 'name' => $arrangement->getName(), 'groupNames' => array_map( fn ($group) => $group->getName(), $original->getGroupsForArrangement($arrangement), ), ]; } $ccli = [ 'author' => $original->getCcliAuthor(), 'song_title' => $original->getCcliSongTitle(), 'publisher' => $original->getCcliPublisher(), 'copyright_year' => $original->getCcliCopyrightYear(), 'song_number' => $original->getCcliSongNumber(), 'display' => $original->getCcliDisplay(), 'artist_credits' => $original->getCcliArtistCredits(), 'album' => $original->getCcliAlbum(), ]; $generated = ProFileGenerator::generate($original->getName(), $groups, $arrangements, $ccli); $filePath = $this->tmpDir . '/test-roundtrip.pro'; ProFileWriter::write($generated, $filePath); $roundTrip = ProFileReader::read($filePath); $this->assertSame($original->getName(), $roundTrip->getName()); $this->assertSame( array_map(fn ($group) => $group->getName(), $original->getGroups()), array_map(fn ($group) => $group->getName(), $roundTrip->getGroups()), ); foreach ($original->getGroups() as $group) { $actualGroup = $roundTrip->getGroupByName($group->getName()); $this->assertNotNull($actualGroup); $expectedSlides = $original->getSlidesForGroup($group); $actualSlides = $roundTrip->getSlidesForGroup($actualGroup); $this->assertCount(count($expectedSlides), $actualSlides); foreach ($expectedSlides as $index => $expectedSlide) { $actualSlide = $actualSlides[$index]; $this->assertSame($expectedSlide->getPlainText(), $actualSlide->getPlainText()); $this->assertSame($expectedSlide->hasTranslation(), $actualSlide->hasTranslation()); if ($expectedSlide->hasTranslation()) { $this->assertSame( $expectedSlide->getTranslation()?->getPlainText(), $actualSlide->getTranslation()?->getPlainText(), ); } } } $this->assertSame( array_map(fn ($arrangement) => $arrangement->getName(), $original->getArrangements()), array_map(fn ($arrangement) => $arrangement->getName(), $roundTrip->getArrangements()), ); foreach ($original->getArrangements() as $arrangement) { $roundTripArrangement = $roundTrip->getArrangementByName($arrangement->getName()); $this->assertNotNull($roundTripArrangement); $expectedNames = array_map( fn ($group) => $group->getName(), $original->getGroupsForArrangement($arrangement), ); $actualNames = array_map( fn ($group) => $group->getName(), $roundTrip->getGroupsForArrangement($roundTripArrangement), ); $this->assertSame($expectedNames, $actualNames); } } #[Test] public function testGenerateAndWriteCreatesFile(): void { $filePath = $this->tmpDir . '/generated.pro'; ProFileGenerator::generateAndWrite( $filePath, 'Write Song', [ [ 'name' => 'Verse 1', 'color' => [0.1, 0.2, 0.3, 1.0], 'slides' => [ ['text' => 'Line 1'], ], ], ], [ ['name' => 'normal', 'groupNames' => ['Verse 1']], ], ); $this->assertFileExists($filePath); $song = ProFileReader::read($filePath); $this->assertSame('Write Song', $song->getName()); } }