pp-planer/tests/Feature/CcliPasteParserScaffoldTest.php

103 lines
3.2 KiB
PHP

<?php
use App\Services\CcliPasteParser;
use App\Services\DTO\ParsedCcliSection;
use App\Services\DTO\ParsedCcliSong;
test('CcliPasteParser can be instantiated with no arguments', function (): void {
$parser = new CcliPasteParser();
expect($parser)->toBeInstanceOf(CcliPasteParser::class);
});
test('CcliPasteParser can be instantiated with closure injections', function (): void {
$parser = new CcliPasteParser(
sectionDetector: fn (string $line): bool => str_starts_with($line, 'Verse'),
metadataDetector: fn (string $line): bool => str_contains($line, '©'),
);
expect($parser)->toBeInstanceOf(CcliPasteParser::class);
});
test('CcliPasteParser resolves from Laravel container', function (): void {
$parser = app(CcliPasteParser::class);
expect($parser)->toBeInstanceOf(CcliPasteParser::class);
});
test('CcliPasteParser::parse returns ParsedCcliSong DTO', function (): void {
$parser = new CcliPasteParser();
$result = $parser->parse("Test Song\nTest Artist\n\nVerse 1\nSome text");
expect($result)->toBeInstanceOf(ParsedCcliSong::class);
});
test('ParsedCcliSong DTO has all required properties', function (): void {
$song = new ParsedCcliSong(
title: 'Test Song',
author: 'Test Author',
ccliId: '9999001',
year: '2024',
copyrightText: '© 2024 Test',
sourceUrl: 'https://songselect.ccli.com/Songs/9999001',
sections: [],
);
expect($song->title)->toBe('Test Song');
expect($song->author)->toBe('Test Author');
expect($song->ccliId)->toBe('9999001');
expect($song->year)->toBe('2024');
expect($song->copyrightText)->toBe('© 2024 Test');
expect($song->sourceUrl)->toContain('songselect.ccli.com');
expect($song->sections)->toBeArray();
});
test('ParsedCcliSection DTO has all required properties including linesTranslated', function (): void {
$section = new ParsedCcliSection(
label: 'Verse 1',
kind: 'Verse',
number: '1',
modifier: null,
lines: ['Line 1', 'Line 2'],
linesTranslated: ['Zeile 1', 'Zeile 2'],
);
expect($section->label)->toBe('Verse 1');
expect($section->kind)->toBe('Verse');
expect($section->number)->toBe('1');
expect($section->modifier)->toBeNull();
expect($section->lines)->toBe(['Line 1', 'Line 2']);
expect($section->linesTranslated)->toBe(['Zeile 1', 'Zeile 2']);
});
test('ParsedCcliSection linesTranslated defaults to null', function (): void {
$section = new ParsedCcliSection(
label: 'Chorus',
kind: 'Chorus',
number: null,
modifier: null,
lines: ['Line 1'],
);
expect($section->linesTranslated)->toBeNull();
});
test('CcliPasteParser can be injected with closure override in container', function (): void {
$called = false;
$fakeParser = new CcliPasteParser(
sectionDetector: function () use (&$called): bool {
$called = true;
return true;
},
);
app()->instance(CcliPasteParser::class, $fakeParser);
$resolved = app(CcliPasteParser::class);
expect($resolved)->toBe($fakeParser);
app()->forgetInstance(CcliPasteParser::class);
});