'DE', 'phone' => '49', 'en' => 'Germany', 'de' => 'Deutschland', 'es' => 'Alemania', 'fr' => 'Allemagne', 'it' => 'Germania', 'ru' => 'Германия', ]); $shipping = Shipping::create(['name' => 'Standard', 'active' => true]); ShippingPrice::create([ 'shipping_id' => $shipping->id, 'price' => 4.90, 'price_comp' => 0, 'num_comp' => 0, 'tax_rate' => 19, 'weight_from' => 1, 'weight_to' => 100000, ]); return ShippingCountry::create(['shipping_id' => $shipping->id, 'country_id' => $country->id]); } function callPortalAboMethod(string $method, array $args = []) { $controller = app(AboController::class); $reflection = new ReflectionMethod($controller, $method); return $reflection->invoke($controller, ...$args); } function findSubscriptionRows(int $productId, bool $addon): Collection { return Yard::instance('subscription')->search(function ($item) use ($productId, $addon) { return (int) $item->id === $productId && (bool) ($item->options->abo_addon ?? false) === $addon; }); } beforeEach(function () { $this->shippingCountry = makePortalOneTimeEnv(); $yard = Yard::instance('subscription'); $yard->destroy(); $yard->setShippingCountryWithPrice($this->shippingCountry->id, 'abo-ot-customer'); }); afterEach(function () { Yard::instance('subscription')->destroy(); }); it('übernimmt onetime_product_qty als getrennte Einmal-Cart-Zeilen', function () { $product = makeProduct(['3'], 25.50, 19); request()->replace(['onetime_product_qty' => [$product->id => 2]]); callPortalAboMethod('oneTimeProductsToCart'); $rows = findSubscriptionRows($product->id, true); expect($rows)->toHaveCount(1) ->and((int) $rows->first()->qty)->toBe(2) ->and((bool) $rows->first()->options->abo_addon)->toBeTrue(); }); it('ignoriert Produkte außerhalb des Einmal-Sortiments', function () { $aboOnlyProduct = makeProduct(['12'], 90, 19); request()->replace(['onetime_product_qty' => [$aboOnlyProduct->id => 1]]); callPortalAboMethod('oneTimeProductsToCart'); expect(Yard::instance('subscription')->content())->toHaveCount(0); }); it('entfernt mit Menge 0 nur die Einmal-Zeile, die Abo-Zeile bleibt', function () { $product = makeProduct(['3', '12'], 90, 19); callPortalAboMethod('addProductToCart', [$product, 1]); request()->replace(['onetime_product_qty' => [$product->id => 2]]); callPortalAboMethod('oneTimeProductsToCart'); expect(findSubscriptionRows($product->id, true))->toHaveCount(1) ->and(findSubscriptionRows($product->id, false))->toHaveCount(1); request()->replace(['onetime_product_qty' => [$product->id => 0]]); callPortalAboMethod('oneTimeProductsToCart'); expect(findSubscriptionRows($product->id, true))->toHaveCount(0) ->and(findSubscriptionRows($product->id, false))->toHaveCount(1); }); it('lässt die Basis-/Upgrade-Logik Einmal-Zeilen unangetastet', function () { $product = makeProduct(['3', '13'], 50, 19); request()->replace(['onetime_product_qty' => [$product->id => 3]]); callPortalAboMethod('oneTimeProductsToCart'); callPortalAboMethod('addProductToCart', [$product, 1]); $addonRows = findSubscriptionRows($product->id, true); $regularRows = findSubscriptionRows($product->id, false); expect($addonRows)->toHaveCount(1) ->and((int) $addonRows->first()->qty)->toBe(3) ->and($regularRows)->toHaveCount(1) ->and((int) $regularRows->first()->qty)->toBe(1); }); it('zählt Einmal-Zeilen nicht als Basis-Produkt', function () { $addonWithBaseShowOn = makeProduct(['3', '12'], 90, 19); request()->replace(['onetime_product_qty' => [$addonWithBaseShowOn->id => 1]]); callPortalAboMethod('oneTimeProductsToCart'); expect(AboHelper::aboHasBaseProduct(Yard::instance('subscription')->getContentByOrder()))->toBeFalse(); $baseProduct = makeProduct(['12'], 90, 19); callPortalAboMethod('addProductToCart', [$baseProduct, 1]); expect(AboHelper::aboHasBaseProduct(Yard::instance('subscription')->getContentByOrder()))->toBeTrue(); });