pp-planer/tests/Feature/MacroAssignmentControllerTest.php
Thorsten Bus 6ce5b6e018 feat(controllers): add macro/label import + global assignment + service override controllers and routes
- MacroImportController + LabelImportController: POST endpoints accepting uploaded .bin files,
  delegating to MacrosImportService / LabelsImportService and returning import stats / warnings as JSON.
  Generic German 422 error if parser rejects the file.
- MacroAssignmentController: index renders Settings Inertia page with assignments / macros / labels /
  collections / last-import metadata. store/update/destroy/reorder for global MacroAssignment rows.
- ServiceMacroOverrideController: store snapshots all matching global MacroAssignments into
  service-specific rows when a service opts to override; destroy removes both override and
  service-specific assignments. storeAssignment / updateAssignment / destroyAssignment manage the
  per-service rows directly.
- routes/web.php: 12 new named routes inside the auth middleware group; reorder route placed before
  {macroAssignment} parameter route to avoid capture conflict.
- Tests: 19 new Pest tests across 4 feature files (54 assertions). Full suite 376 passed.
2026-05-03 23:17:04 +02:00

109 lines
3.6 KiB
PHP

<?php
use App\Models\Label;
use App\Models\Macro;
use App\Models\MacroAssignment;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
test('store requires authentication', function () {
$response = $this->post(route('settings.macro-assignments.store'), []);
$response->assertRedirect(route('login'));
});
test('store creates macro assignment', function () {
$user = User::factory()->create();
$macro = Macro::factory()->create();
$response = $this->actingAs($user)
->postJson(route('settings.macro-assignments.store'), [
'part_type' => 'song',
'macro_id' => $macro->id,
'position' => 'all_slides',
'order' => 0,
]);
$response->assertStatus(200)->assertJson(['success' => true]);
expect(MacroAssignment::count())->toBe(1);
expect(MacroAssignment::first()->part_type)->toBe('song');
});
test('store with by_label position and label_id', function () {
$user = User::factory()->create();
$macro = Macro::factory()->create();
$label = Label::factory()->create();
$response = $this->actingAs($user)
->postJson(route('settings.macro-assignments.store'), [
'part_type' => 'sermon',
'macro_id' => $macro->id,
'position' => 'by_label',
'label_id' => $label->id,
'order' => 1,
]);
$response->assertStatus(200);
$assignment = MacroAssignment::first();
expect($assignment->label_id)->toBe($label->id);
expect($assignment->position)->toBe('by_label');
});
test('update modifies existing assignment', function () {
$user = User::factory()->create();
$macro = Macro::factory()->create();
$assignment = MacroAssignment::create([
'part_type' => 'song',
'macro_id' => $macro->id,
'position' => 'all_slides',
'order' => 0,
]);
$response = $this->actingAs($user)
->patchJson(route('settings.macro-assignments.update', $assignment), [
'position' => 'first_slide',
'order' => 5,
]);
$response->assertStatus(200)->assertJson(['success' => true]);
expect($assignment->fresh()->position)->toBe('first_slide');
expect($assignment->fresh()->order)->toBe(5);
});
test('destroy deletes macro assignment', function () {
$user = User::factory()->create();
$macro = Macro::factory()->create();
$assignment = MacroAssignment::create([
'part_type' => 'song',
'macro_id' => $macro->id,
'position' => 'all_slides',
'order' => 0,
]);
$response = $this->actingAs($user)
->deleteJson(route('settings.macro-assignments.destroy', $assignment));
$response->assertStatus(200)->assertJson(['success' => true]);
expect(MacroAssignment::count())->toBe(0);
});
test('reorder updates order on multiple assignments', function () {
$user = User::factory()->create();
$macro = Macro::factory()->create();
$a1 = MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'all_slides', 'order' => 0]);
$a2 = MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'all_slides', 'order' => 1]);
$response = $this->actingAs($user)
->postJson(route('settings.macro-assignments.reorder'), [
'assignments' => [
['id' => $a1->id, 'order' => 5],
['id' => $a2->id, 'order' => 3],
],
]);
$response->assertStatus(200);
expect($a1->fresh()->order)->toBe(5);
expect($a2->fresh()->order)->toBe(3);
});