create(); // Support has customers.manage (can suspend, impersonate) but never had // customers.grant_plan — giving away service is a bigger deal than a // reversible suspend, and the seed migration deliberately keeps this one // to Owner. A capability check that only hid the button would still let // this request through. Livewire::actingAs(operator('Support'), 'operator') ->test(GrantPlan::class, ['uuid' => $customer->uuid]) ->assertForbidden(); }); it('hides the grant button from an operator without the capability', function () { Customer::factory()->create(); Livewire::actingAs(operator('Support'), 'operator') ->test(Customers::class) ->assertDontSee(__('admin.grant_action')); }); it('shows the grant button to the Owner', function () { Customer::factory()->create(); Livewire::actingAs(operator('Owner'), 'operator') ->test(Customers::class) ->assertSee(__('admin.grant_action')); }); it('grants a free package to a customer with no contract yet', function () { Queue::fake(); $customer = Customer::factory()->create(); $owner = operator('Owner'); Livewire::actingAs($owner, 'operator') ->test(GrantPlan::class, ['uuid' => $customer->uuid]) ->set('plan', 'team') ->set('term', 'monthly') ->set('datacenter', 'fsn') ->set('priceEuros', '0') ->set('note', 'Testkunde') ->call('grant') ->assertHasNoErrors(); $subscription = Subscription::query()->where('customer_id', $customer->id)->sole(); expect($subscription->price_cents)->toBe(0) ->and($subscription->isGranted())->toBeTrue() ->and($subscription->granted_by)->toBe($owner->id); Queue::assertPushed(AdvanceRunJob::class); }); it('grants a discounted module onto an existing contract', function () { $customer = Customer::factory()->create(); Subscription::factory()->create(['customer_id' => $customer->id, 'status' => 'active']); $owner = operator('Owner'); Livewire::actingAs($owner, 'operator') ->test(GrantPlan::class, ['uuid' => $customer->uuid]) ->assertSet('kind', 'addon') // a contract already exists — default to the module form ->set('addonKey', 'priority_support') ->set('quantity', 1) ->set('priceEuros', '5,00') ->call('grant') ->assertHasNoErrors(); $addon = SubscriptionAddon::query()->where('addon_key', 'priority_support')->sole(); expect($addon->price_cents)->toBe(500) ->and($addon->isGranted())->toBeTrue() ->and($addon->granted_by)->toBe($owner->id); }); it('shows who granted what, when, and until when', function () { $customer = Customer::factory()->create(); $owner = operator('Owner'); $until = now()->addMonths(3); Subscription::factory()->create([ 'customer_id' => $customer->id, 'status' => 'active', 'price_cents' => 0, 'granted_by' => $owner->id, 'granted_at' => now(), 'grant_note' => 'Sponsoring', 'granted_until' => $until, 'catalogue_price_cents' => 17900, ]); Livewire::actingAs($owner, 'operator') ->test(GrantPlan::class, ['uuid' => $customer->uuid]) ->assertSee($owner->name) ->assertSee('Sponsoring') ->assertSee($until->local()->isoFormat('D. MMM YYYY')); });