create(); $user = User::factory()->create(['email' => $customer->email]); $order = Order::factory()->withSubscription()->for($customer)->create(['plan' => $plan]); $instance = Instance::factory()->for($customer)->create([ 'order_id' => $order->id, 'plan' => $plan, 'status' => 'active', ]); $order->subscription->update(['instance_id' => $instance->id]); // purchase() refuses outright without a Stripe key for the active mode // (Task 5) — the refusal this test is about must not be masked by that // earlier one. withStripeSecret(); return [$customer, $user]; } it('weist eine Buchung von collabora_pro am Formular vorbei ab, solange Office nicht verkauft wird', function () { // Absichtlich NICHT über einen fehlenden Knopf geprüft: das würde nur // zeigen, dass die Anzeige geschlossen ist. Dieser Aufruf geht am // Formular vorbei — genau der Weg, den ein zweites Browser-Fenster, eine // alte Sitzung oder ein direkter Aufruf des Komponentennamens auch nähme. [$customer, $user] = officeShopper('team'); Livewire::actingAs($user)->test(Billing::class) ->call('purchase', 'addon', 'collabora_pro') ->assertDispatched('notify', message: __('billing.addon_not_on_sale', [ 'module' => __('billing.addon.collabora_pro.name'), ])); // Kein Auftrag, also nichts, das später fälschlich zur Buchung würde. expect(Order::query()->where('customer_id', $customer->id)->where('type', 'addon')->exists())->toBeFalse(); }); it('zeigt die Office-Karte im Portal nicht mehr an, solange sie ohnehin abgewiesen würde', function () { [, $user] = officeShopper('team'); // Team trägt `collabora_pro` nicht in `unavailable_on` — ohne den neuen // Riegel stünde die Karte hier also, mit einem Kauf-Knopf, der beim // Anklicken nur die Meldung aus dem Test oben gezeigt hätte. Livewire::actingAs($user)->test(Billing::class) ->assertDontSee(__('billing.addon.collabora_pro.name')); }); it('lässt die anderen Module unberührt, sowohl in der Anzeige als auch bei der Buchung', function () { // Der Riegel gilt nur `collabora_pro` (und, seit // tests/Feature/Billing/ExtraBackupsNotSoldTest.php, `extra_backups`) — // für alles andere muss saleRefusal() weiterhin null bleiben, sonst hätte // diese Änderung den ganzen Shop zugesperrt statt zweier einzelner // Module. `extra_backups` steht deshalb absichtlich NICHT mehr in dieser // Liste. $catalogue = app(AddonCatalogue::class); foreach (['priority_support', 'custom_domain', AddonCatalogue::STORAGE] as $key) { expect($catalogue->saleRefusal($key))->toBeNull(); } [, $user] = officeShopper('team'); Livewire::actingAs($user)->test(Billing::class) ->call('purchase', 'addon', 'priority_support') ->assertDispatched('notify', message: __('billing.purchased')); expect(Order::query()->where('type', 'addon')->where('addon_key', 'priority_support')->exists())->toBeTrue(); });