create(); $response = $this->post(route('services.macro-overrides.store', $service), ['part_type' => 'song']); $response->assertRedirect(route('login')); }); test('store creates override and snapshots global assignments', function () { $user = User::factory()->create(); $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' => 'song', 'macro_id' => $macro->id, 'position' => 'first_slide', 'order' => 1]); $response = $this->actingAs($user) ->postJson(route('services.macro-overrides.store', $service), ['part_type' => 'song']); $response->assertStatus(200)->assertJson(['success' => true]); expect(ServiceMacroOverride::where('service_id', $service->id)->where('part_type', 'song')->exists())->toBeTrue(); expect(ServiceMacroAssignment::where('service_id', $service->id)->count())->toBe(2); }); test('store does not snapshot assignments from different part_type', function () { $user = User::factory()->create(); $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]); $this->actingAs($user) ->postJson(route('services.macro-overrides.store', $service), ['part_type' => 'song']); expect(ServiceMacroAssignment::where('service_id', $service->id)->count())->toBe(1); expect(ServiceMacroAssignment::where('service_id', $service->id)->first()->part_type)->toBe('song'); }); test('destroy removes override and service-specific assignments', function () { $user = User::factory()->create(); $service = Service::factory()->create(); $macro = Macro::factory()->create(); ServiceMacroOverride::create(['service_id' => $service->id, 'part_type' => 'song']); ServiceMacroAssignment::create([ 'service_id' => $service->id, 'part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'all_slides', 'order' => 0, ]); $response = $this->actingAs($user) ->deleteJson(route('services.macro-overrides.destroy', $service), ['part_type' => 'song']); $response->assertStatus(200); expect(ServiceMacroOverride::where('service_id', $service->id)->count())->toBe(0); expect(ServiceMacroAssignment::where('service_id', $service->id)->count())->toBe(0); }); test('storeAssignment creates service-level assignment', function () { $user = User::factory()->create(); $service = Service::factory()->create(); $macro = Macro::factory()->create(); $response = $this->actingAs($user) ->postJson(route('services.macro-assignments.store', $service), [ 'part_type' => 'sermon', 'macro_id' => $macro->id, 'position' => 'last_slide', 'order' => 0, ]); $response->assertStatus(200)->assertJson(['success' => true]); expect(ServiceMacroAssignment::count())->toBe(1); expect(ServiceMacroAssignment::first()->service_id)->toBe($service->id); }); test('destroyAssignment removes service-level assignment', function () { $user = User::factory()->create(); $service = Service::factory()->create(); $macro = Macro::factory()->create(); $assignment = ServiceMacroAssignment::create([ 'service_id' => $service->id, 'part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'all_slides', 'order' => 0, ]); $response = $this->actingAs($user) ->deleteJson(route('services.macro-assignments.destroy', [$service, $assignment])); $response->assertStatus(200); expect(ServiceMacroAssignment::count())->toBe(0); });