pp-planer/tests/Feature/MacroResolutionServiceTest.php

116 lines
5.3 KiB
PHP

<?php
use App\Models\Label;
use App\Models\Macro;
use App\Models\MacroAssignment;
use App\Models\Service;
use App\Models\ServiceMacroAssignment;
use App\Models\ServiceMacroOverride;
use App\Services\MacroResolutionService;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
test('returns empty when no assignments exist', function () {
$service = Service::factory()->create();
$resolver = app(MacroResolutionService::class);
expect($resolver->resolveAssignmentsForPart($service, 'song'))->toBeEmpty();
});
test('returns global assignments when no override', function () {
$service = Service::factory()->create();
$macro = Macro::factory()->create();
MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'all_slides', 'order' => 0]);
$resolver = app(MacroResolutionService::class);
$resolved = $resolver->resolveAssignmentsForPart($service, 'song');
expect($resolved)->toHaveCount(1);
expect($resolved->first()->macro->id)->toBe($macro->id);
});
test('override wins over globals', function () {
$service = Service::factory()->create();
$macroA = Macro::factory()->create(['name' => 'Global']);
$macroB = Macro::factory()->create(['name' => 'Override']);
MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macroA->id, 'position' => 'all_slides', 'order' => 0]);
ServiceMacroOverride::create(['service_id' => $service->id, 'part_type' => 'song']);
ServiceMacroAssignment::create(['service_id' => $service->id, 'part_type' => 'song', 'macro_id' => $macroB->id, 'position' => 'all_slides', 'order' => 0]);
$resolver = app(MacroResolutionService::class);
$resolved = $resolver->resolveAssignmentsForPart($service, 'song');
expect($resolved)->toHaveCount(1);
expect($resolved->first()->macro->name)->toBe('Override');
});
test('hidden macros are filtered out', function () {
$service = Service::factory()->create();
$macro = Macro::factory()->create(['hidden_at' => now()]);
MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'all_slides', 'order' => 0]);
$resolver = app(MacroResolutionService::class);
expect($resolver->resolveAssignmentsForPart($service, 'song'))->toBeEmpty();
});
test('macrosForSlide with all_slides matches every slide', function () {
$service = Service::factory()->create();
$macro = Macro::factory()->create();
MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'all_slides', 'order' => 0]);
$resolver = app(MacroResolutionService::class);
$result = $resolver->macrosForSlide($service, 'song', ['index' => 0, 'total' => 3, 'label_id' => null]);
expect($result)->toHaveCount(1);
expect($result[0]['uuid'])->toBe($macro->uuid);
});
test('macrosForSlide with first_slide only matches index 0', function () {
$service = Service::factory()->create();
$macro = Macro::factory()->create();
MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'first_slide', 'order' => 0]);
$resolver = app(MacroResolutionService::class);
expect($resolver->macrosForSlide($service, 'song', ['index' => 0, 'total' => 3, 'label_id' => null]))->toHaveCount(1);
expect($resolver->macrosForSlide($service, 'song', ['index' => 1, 'total' => 3, 'label_id' => null]))->toHaveCount(0);
});
test('macrosForSlide stacking — multiple matching assignments produce multiple macros', function () {
$service = Service::factory()->create();
$macro1 = Macro::factory()->create();
$macro2 = Macro::factory()->create();
MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro1->id, 'position' => 'all_slides', 'order' => 0]);
MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro2->id, 'position' => 'first_slide', 'order' => 1]);
$resolver = app(MacroResolutionService::class);
$result = $resolver->macrosForSlide($service, 'song', ['index' => 0, 'total' => 3, 'label_id' => null]);
expect($result)->toHaveCount(2);
});
test('macrosForSlide with by_label matches only matching label_id', function () {
$service = Service::factory()->create();
$label = Label::factory()->create();
$macro = Macro::factory()->create();
MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'by_label', 'label_id' => $label->id, 'order' => 0]);
$resolver = app(MacroResolutionService::class);
expect($resolver->macrosForSlide($service, 'song', ['index' => 0, 'total' => 3, 'label_id' => $label->id]))->toHaveCount(1);
expect($resolver->macrosForSlide($service, 'song', ['index' => 0, 'total' => 3, 'label_id' => 9999]))->toHaveCount(0);
});
test('countAssignmentsForPart returns correct count', function () {
$service = Service::factory()->create();
$macro = Macro::factory()->create();
MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'all_slides', 'order' => 0]);
MacroAssignment::create(['part_type' => 'sermon', 'macro_id' => $macro->id, 'position' => 'all_slides', 'order' => 0]);
$resolver = app(MacroResolutionService::class);
expect($resolver->countAssignmentsForPart($service, 'song'))->toBe(1);
expect($resolver->countAssignmentsForPart($service, 'sermon'))->toBe(1);
expect($resolver->countAssignmentsForPart($service, 'information'))->toBe(0);
});