160 lines
5.3 KiB
PHP
160 lines
5.3 KiB
PHP
<?php
|
||
|
||
use App\Models\ServiceAgendaItem;
|
||
use App\Services\AgendaMatcherService;
|
||
|
||
beforeEach(function () {
|
||
$this->service = new AgendaMatcherService;
|
||
});
|
||
|
||
// Exact match
|
||
test('matches exact title', function () {
|
||
expect($this->service->matches('Predigt', 'Predigt'))->toBeTrue();
|
||
});
|
||
|
||
// Wildcard suffix
|
||
test('matches wildcard suffix pattern', function () {
|
||
expect($this->service->matches('Predigt – Thema XY', 'Predigt*'))->toBeTrue();
|
||
});
|
||
|
||
// Wildcard prefix
|
||
test('matches wildcard prefix pattern', function () {
|
||
expect($this->service->matches('Die Predigt', '*Predigt'))->toBeTrue();
|
||
});
|
||
|
||
// Wildcard both
|
||
test('matches wildcard both sides pattern', function () {
|
||
expect($this->service->matches('Die Predigt heute', '*Predigt*'))->toBeTrue();
|
||
});
|
||
|
||
// Case insensitive
|
||
test('matches case insensitive', function () {
|
||
expect($this->service->matches('Predigt – Thema', 'predigt*'))->toBeTrue();
|
||
});
|
||
|
||
// No match
|
||
test('does not match unrelated title', function () {
|
||
expect($this->service->matches('Lobpreis', 'Predigt*'))->toBeFalse();
|
||
});
|
||
|
||
// Multiple patterns — matchesAny
|
||
test('matchesAny returns true if any pattern matches', function () {
|
||
$patterns = ['Predigt*', 'Sermon*'];
|
||
expect($this->service->matchesAny('Predigt – Thema', $patterns))->toBeTrue();
|
||
});
|
||
|
||
test('matchesAny returns false if no pattern matches', function () {
|
||
$patterns = ['Predigt*', 'Sermon*'];
|
||
expect($this->service->matchesAny('Lobpreis', $patterns))->toBeFalse();
|
||
});
|
||
|
||
// findFirstMatch returns matching item
|
||
test('findFirstMatch returns first matching ServiceAgendaItem', function () {
|
||
$items = [
|
||
ServiceAgendaItem::factory()->create(['title' => 'Lobpreis']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Predigt – Thema']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Gebet']),
|
||
];
|
||
|
||
$result = $this->service->findFirstMatch($items, 'Predigt*');
|
||
|
||
expect($result)->toBeInstanceOf(ServiceAgendaItem::class);
|
||
expect($result->title)->toBe('Predigt – Thema');
|
||
});
|
||
|
||
test('findFirstMatch returns null when no match', function () {
|
||
$items = [
|
||
ServiceAgendaItem::factory()->create(['title' => 'Lobpreis']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Gebet']),
|
||
];
|
||
|
||
$result = $this->service->findFirstMatch($items, 'Predigt*');
|
||
|
||
expect($result)->toBeNull();
|
||
});
|
||
|
||
// filterBetween with both start and end
|
||
test('filterBetween filters items between start and end (both excluded)', function () {
|
||
$items = [
|
||
ServiceAgendaItem::factory()->create(['title' => 'Info']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Start']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Lied 1']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Lied 2']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'End']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Segen']),
|
||
];
|
||
|
||
$result = $this->service->filterBetween($items, 'Start', 'End');
|
||
|
||
expect($result)->toHaveCount(2);
|
||
expect($result[0]->title)->toBe('Lied 1');
|
||
expect($result[1]->title)->toBe('Lied 2');
|
||
});
|
||
|
||
// filterBetween with start only
|
||
test('filterBetween from start boundary to end of items', function () {
|
||
$items = [
|
||
ServiceAgendaItem::factory()->create(['title' => 'Info']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Start']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Lied 1']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Lied 2']),
|
||
];
|
||
|
||
$result = $this->service->filterBetween($items, 'Start', null);
|
||
|
||
expect($result)->toHaveCount(2);
|
||
expect($result[0]->title)->toBe('Lied 1');
|
||
expect($result[1]->title)->toBe('Lied 2');
|
||
});
|
||
|
||
// filterBetween with neither
|
||
test('filterBetween with no start or end patterns returns all items', function () {
|
||
$items = [
|
||
ServiceAgendaItem::factory()->create(['title' => 'Info']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Lied 1']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Lied 2']),
|
||
];
|
||
|
||
$result = $this->service->filterBetween($items, null, null);
|
||
|
||
expect($result)->toHaveCount(3);
|
||
});
|
||
|
||
// filterBetween with no matching start
|
||
test('filterBetween with no matching start pattern returns empty array', function () {
|
||
$items = [
|
||
ServiceAgendaItem::factory()->create(['title' => 'Lied 1']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Lied 2']),
|
||
];
|
||
|
||
$result = $this->service->filterBetween($items, 'Nonexistent*', null);
|
||
|
||
expect($result)->toBeEmpty();
|
||
});
|
||
|
||
// findFirstMatch with comma-separated patterns
|
||
test('findFirstMatch splits comma-separated patterns and matches', function () {
|
||
$items = [
|
||
ServiceAgendaItem::factory()->create(['title' => 'Lobpreis']),
|
||
ServiceAgendaItem::factory()->create(['title' => 'Predigt – Thema']),
|
||
];
|
||
|
||
$result = $this->service->findFirstMatch($items, 'Lied*,Predigt*');
|
||
|
||
expect($result)->toBeInstanceOf(ServiceAgendaItem::class);
|
||
expect($result->title)->toBe('Predigt – Thema');
|
||
});
|
||
|
||
// Edge case: empty items array
|
||
test('findFirstMatch with empty items returns null', function () {
|
||
$result = $this->service->findFirstMatch([], 'Predigt*');
|
||
|
||
expect($result)->toBeNull();
|
||
});
|
||
|
||
test('filterBetween with empty items returns empty array', function () {
|
||
$result = $this->service->filterBetween([], 'Start', 'End');
|
||
|
||
expect($result)->toBeEmpty();
|
||
});
|