stripe = new FakeStripeClient; app()->instance(StripeClient::class, $this->stripe); $family = PlanFamily::create([ 'key' => 'test', 'name' => 'Test', 'tier' => 0, 'sales_enabled' => true, 'internal' => true, ]); $version = app(PlanCatalogue::class)->draft($family, [ 'quota_gb' => 5, 'traffic_gb' => 1000, 'seats' => 3, 'free_months' => 0, 'ram_mb' => 4096, 'cores' => 2, 'disk_gb' => 20, 'performance' => 'standard', 'template_vmid' => 9000, 'features' => [], ], ['monthly' => 100, 'yearly' => 1200]); app(PlanCatalogue::class)->publish($version); }); it('zeigt ein internes Paket nicht im Verkauf', function () { expect(array_keys(app(PlanCatalogue::class)->sellable()))->not->toContain('test'); }); it('lässt ein internes Paket weiterhin verschenken', function () { // currentVersion() ist der Weg, den GrantPlan benutzt — wirft er hier, // ist das Verschenken mit abgeschaltet, und genau das soll `internal` // gerade NICHT tun. expect(app(PlanCatalogue::class)->currentVersion('test')->quota_gb)->toBe(5); }); it('lehnt einen Checkout auf ein internes Paket ab, nicht unterscheidbar von einem unbekannten', function () { $buyer = User::factory()->create(['email_verified_at' => now()]); // Eine URL ist keine Liste: dass "test" in keinem Preisblatt steht, hält // niemanden davon ab, den Schlüssel direkt zu posten. Erwartet wird // dieselbe Antwort wie für einen Schlüssel, den es gar nicht gibt — wer // die Preisliste nicht kennt, soll aus der Antwort nicht lernen können, // dass es dieses Paket gibt. $this->actingAs($buyer) ->post(route('checkout.start'), ['plan' => 'test', 'terms_accepted' => '1']) ->assertSessionHasErrors(['plan' => __('checkout.plan_gone')]); $this->actingAs($buyer) ->post(route('checkout.start'), ['plan' => 'gibt-es-nicht', 'terms_accepted' => '1']) ->assertSessionHasErrors(['plan' => __('checkout.plan_gone')]); expect($this->stripe->checkouts)->toBeEmpty(); });