stripe = new FakeStripeClient; app()->instance(StripeClient::class, $this->stripe); }); it('records the mode its objects were created in', function () { OperatingMode::set(OperatingMode::Test); $this->artisan('stripe:sync-catalogue')->assertSuccessful(); expect(StripeCatalogueMode::recorded())->toBe(OperatingMode::Test) ->and(StripeCatalogueMode::hasStoredObjects())->toBeTrue(); }); it('records nothing on a dry run, which creates nothing', function () { OperatingMode::set(OperatingMode::Test); $this->artisan('stripe:sync-catalogue', ['--dry-run' => true])->assertSuccessful(); expect(StripeCatalogueMode::recorded())->toBeNull(); }); it('refuses to work into a catalogue that belongs to the other account', function () { OperatingMode::set(OperatingMode::Test); $this->artisan('stripe:sync-catalogue')->assertSuccessful(); OperatingMode::set(OperatingMode::Live); $this->artisan('stripe:sync-catalogue')->assertFailed(); // Und die Zeile lügt danach nicht: der Katalog gehört weiterhin dem // Testkonto, weil dieser Lauf nichts angelegt hat. expect(StripeCatalogueMode::recorded())->toBe(OperatingMode::Test); }); it('syncs into the new account once the stale ids are cleared', function () { OperatingMode::set(OperatingMode::Test); $this->artisan('stripe:sync-catalogue')->assertSuccessful(); OperatingMode::set(OperatingMode::Live); // Was der `breaks`-Satz und die Fehlermeldung dem Betreiber auftragen — // Zeiger UND Register, weil PlanPrices::inStep() für den Netto-Preis eines // Reverse-Charge-Kunden allein das Register fragt. DB::table('plan_families')->update(['stripe_product_id' => null]); DB::table('plan_prices')->update(['stripe_price_id' => null]); DB::table('stripe_plan_prices')->delete(); DB::table('stripe_addon_prices')->delete(); $this->artisan('stripe:sync-catalogue')->assertSuccessful(); expect(StripeCatalogueMode::recorded())->toBe(OperatingMode::Live) ->and(PlanPrice::query()->whereNotNull('stripe_price_id')->exists())->toBeTrue(); });