diff --git a/.env.testing b/.env.testing index 299f945da..e87932525 100644 --- a/.env.testing +++ b/.env.testing @@ -42,4 +42,4 @@ MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" SHOP_MAIL_FROM=test@example.com -ADMIN_MAIL_TO=test@example.com \ No newline at end of file +ADMIN_MAIL_TO=test@example.com diff --git a/.gitignore b/.gitignore index f8f0d01e0..a19a6d127 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,5 @@ yarn.lock .php_cs.cache storage/ storage/*.key - +/docker-compose-collection/ /resources/themes/velocity/* - diff --git a/packages/Webkul/Admin/src/Resources/views/cms/create.blade.php b/packages/Webkul/Admin/src/Resources/views/cms/create.blade.php index cbe5f131c..2ad5a0f13 100644 --- a/packages/Webkul/Admin/src/Resources/views/cms/create.blade.php +++ b/packages/Webkul/Admin/src/Resources/views/cms/create.blade.php @@ -96,6 +96,7 @@ + diff --git a/packages/Webkul/Admin/src/Resources/views/cms/edit.blade.php b/packages/Webkul/Admin/src/Resources/views/cms/edit.blade.php index bf35f6b7a..052a565d9 100644 --- a/packages/Webkul/Admin/src/Resources/views/cms/edit.blade.php +++ b/packages/Webkul/Admin/src/Resources/views/cms/edit.blade.php @@ -104,12 +104,14 @@ +
+
diff --git a/packages/Webkul/Checkout/src/Cart.php b/packages/Webkul/Checkout/src/Cart.php index 9157dc392..6c2c5df49 100755 --- a/packages/Webkul/Checkout/src/Cart.php +++ b/packages/Webkul/Checkout/src/Cart.php @@ -128,7 +128,7 @@ class Cart { * * @param integer $productId * @param array $data - * @return Cart + * @return Mixed Cart on success, array with warning otherwise */ public function addProduct($productId, $data) { @@ -136,8 +136,9 @@ class Cart { $cart = $this->getCart(); - if (! $cart && ! $cart = $this->create($data)) - return; + if (! $cart && ! $cart = $this->create($data)) { + return ['warning' => __('shop::app.checkout.cart.item.error-add')]; + } $product = $this->productRepository->findOneByField('id', $productId); @@ -157,8 +158,9 @@ class Cart { foreach ($cartProducts as $cartProduct) { $cartItem = $this->getItemByProduct($cartProduct); - if (isset($cartProduct['parent_id'])) + if (isset($cartProduct['parent_id'])) { $cartProduct['parent_id'] = $parentCartItem->id; + } if (! $cartItem) { $cartItem = $this->cartItemRepository->create(array_merge($cartProduct, ['cart_id' => $cart->id])); @@ -166,6 +168,9 @@ class Cart { if (isset($cartProduct['parent_id']) && $cartItem->parent_id != $parentCartItem->id) { $cartItem = $this->cartItemRepository->create(array_merge($cartProduct, ['cart_id' => $cart->id])); } else { + if ($product->getTypeInstance()->showQuantityBox() === false) { + return ['warning' => __('shop::app.checkout.cart.integrity.qty_impossible')]; + } $cartItem = $this->cartItemRepository->update($cartProduct, $cartItem->id); } } diff --git a/packages/Webkul/Checkout/src/Models/Cart.php b/packages/Webkul/Checkout/src/Models/Cart.php index 936215c1c..ba13c788b 100755 --- a/packages/Webkul/Checkout/src/Models/Cart.php +++ b/packages/Webkul/Checkout/src/Models/Cart.php @@ -123,13 +123,29 @@ class Cart extends Model implements CartContract public function hasDownloadableItems() { foreach ($this->items as $item) { - if ($item->type == 'downloadable') + if (stristr($item->type,'downloadable') !== false) { return true; + } } return false; } + /** + * Returns true if cart contains one or many products with quantity box. + * (for example: simple, configurable, virtual) + * @return bool + */ + public function hasProductsWithQuantityBox(): bool + { + foreach ($this->items as $item) { + if ($item->product->getTypeInstance()->showQuantityBox() === true) { + return true; + } + } + return false; + } + /** * Checks if cart has items that allow guest checkout * @@ -145,4 +161,4 @@ class Cart extends Model implements CartContract return true; } -} \ No newline at end of file +} diff --git a/packages/Webkul/Core/src/Helpers/Laravel5Helper.php b/packages/Webkul/Core/src/Helpers/Laravel5Helper.php index 7b8cfb7f2..b15b3d89f 100644 --- a/packages/Webkul/Core/src/Helpers/Laravel5Helper.php +++ b/packages/Webkul/Core/src/Helpers/Laravel5Helper.php @@ -1,4 +1,5 @@ states($productStates)->create($configs['productAttributes'] ?? []);; - $I->createAttributeValues($product->id,$configs['attributeValues'] ?? []); - $I->have(ProductInventory::class, array_merge($configs['productInventory'] ?? [], [ - 'product_id' => $product->id, - 'inventory_source_id' => 1, - ])); - Event::dispatch('catalog.product.create.after', $product); + + switch ($productType) { + case self::DOWNLOADABLE_PRODUCT: + $product = $I->haveDownloadableProduct($configs, $productStates); + break; + + case self::VIRTUAL_PRODUCT: + $product = $I->haveVirtualProduct($configs, $productStates); + break; + + case self::SIMPLE_PRODUCT: + default: + $product = $I->haveSimpleProduct($configs, $productStates); + } + + if ($product !== null) { + Event::dispatch('catalog.product.create.after', $product); + } + return $product; } - private function createAttributeValues($id, array $attributeValues = []) + + /** + * @param array $configs + * @param array $productStates + * + * @return \Webkul\Product\Models\Product + */ + private function haveSimpleProduct(array $configs = [], array $productStates = []): Product + { + $I = $this; + if (!in_array('simple', $productStates)) { + $productStates = array_merge($productStates, ['simple']); + } + + /** @var Product $product */ + $product = $I->createProduct($configs['productAttributes'] ?? [], $productStates); + + $I->createAttributeValues($product->id, $configs['attributeValues'] ?? []); + + $I->createInventory($product->id, $configs['productInventory'] ?? []); + + return $product->refresh(); + } + + /** + * @param array $configs + * @param array $productStates + * + * @return \Webkul\Product\Models\Product + */ + private function haveVirtualProduct(array $configs = [], array $productStates = []): Product + { + $I = $this; + if (!in_array('virtual', $productStates)) { + $productStates = array_merge($productStates, ['virtual']); + } + + /** @var Product $product */ + $product = $I->createProduct($configs['productAttributes'] ?? [], $productStates); + + $I->createAttributeValues($product->id, $configs['attributeValues'] ?? []); + + $I->createInventory($product->id, $configs['productInventory'] ?? []); + + return $product->refresh(); + } + + /** + * @param array $configs + * @param array $productStates + * + * @return \Webkul\Product\Models\Product + */ + private function haveDownloadableProduct(array $configs = [], array $productStates = []): Product + { + $I = $this; + if (!in_array('downloadable', $productStates)) { + $productStates = array_merge($productStates, ['downloadable']); + } + + /** @var Product $product */ + $product = $I->createProduct($configs['productAttributes'] ?? [], $productStates); + + $I->createAttributeValues($product->id, $configs['attributeValues'] ?? []); + + $I->createDownloadableLink($product->id); + + return $product->refresh(); + } + + /** + * @param array $attributes + * @param array $states + * + * @return \Webkul\Product\Models\Product + */ + private function createProduct(array $attributes = [], array $states = []): Product + { + return factory(Product::class)->states($states)->create($attributes); + } + + /** + * @param int $productId + * @param array $inventoryConfig + */ + private function createInventory(int $productId, array $inventoryConfig = []): void + { + $I = $this; + $I->have(ProductInventory::class, array_merge($inventoryConfig, [ + 'product_id' => $productId, + 'inventory_source_id' => 1, + ])); + } + + /** + * @param int $productId + */ + private function createDownloadableLink(int $productId): void + { + $I = $this; + $link = $I->have(ProductDownloadableLink::class, [ + 'product_id' => $productId, + ]); + + $I->have(ProductDownloadableLinkTranslation::class, [ + 'product_downloadable_link_id' => $link->id, + ]); + } + + /** + * @param int $productId + * @param array $attributeValues + */ + private function createAttributeValues(int $productId, array $attributeValues = []): void { $I = $this; $productAttributeValues = [ @@ -100,10 +233,10 @@ class Laravel5Helper extends Laravel5 'weight', ]; foreach ($productAttributeValues as $attribute) { - $data = ['product_id' => $id]; + $data = ['product_id' => $productId]; if (array_key_exists($attribute, $attributeValues)) { $fieldName = self::getAttributeFieldName($attribute); - if (! array_key_exists($fieldName, $data)) { + if (!array_key_exists($fieldName, $data)) { $data[$fieldName] = $attributeValues[$attribute]; } else { $data = [$fieldName => $attributeValues[$attribute]]; diff --git a/packages/Webkul/Product/src/Database/Factories/ProductDownloadableLinkFactory.php b/packages/Webkul/Product/src/Database/Factories/ProductDownloadableLinkFactory.php index 67bace113..d7e0a45e0 100644 --- a/packages/Webkul/Product/src/Database/Factories/ProductDownloadableLinkFactory.php +++ b/packages/Webkul/Product/src/Database/Factories/ProductDownloadableLinkFactory.php @@ -3,6 +3,7 @@ /** @var \Illuminate\Database\Eloquent\Factory $factory */ use Faker\Generator as Faker; +use Webkul\Product\Models\Product; use Webkul\Product\Models\ProductDownloadableLink; use Webkul\Product\Models\ProductDownloadableLinkTranslation; @@ -17,6 +18,9 @@ $factory->define(ProductDownloadableLink::class, function (Faker $faker) { 'type' => 'file', 'price' => 0.0000, 'downloads' => $faker->randomNumber(1), + 'product_id' => function () { + return factory(Product::class)->create()->id; + }, 'created_at' => $now, 'updated_at' => $now, ]; @@ -28,4 +32,3 @@ $factory->define(ProductDownloadableLinkTranslation::class, function (Faker $fak 'title' => $faker->word, ]; }); - diff --git a/packages/Webkul/Product/src/Database/Factories/ProductDownloadableLinkTranslation.php b/packages/Webkul/Product/src/Database/Factories/ProductDownloadableLinkTranslation.php new file mode 100644 index 000000000..28800751e --- /dev/null +++ b/packages/Webkul/Product/src/Database/Factories/ProductDownloadableLinkTranslation.php @@ -0,0 +1,17 @@ +define(ProductDownloadableLinkTranslation::class, function (Faker $faker) { + return [ + 'locale' => 'en', + 'title' => $faker->word, + 'product_downloadable_link_id' => function () { + return factory(ProductDownloadableLink::class)->create()->id; + }, + ]; +}); diff --git a/packages/Webkul/Product/src/Database/Factories/ProductFactory.php b/packages/Webkul/Product/src/Database/Factories/ProductFactory.php index 0caf3ded5..da90315f4 100644 --- a/packages/Webkul/Product/src/Database/Factories/ProductFactory.php +++ b/packages/Webkul/Product/src/Database/Factories/ProductFactory.php @@ -18,6 +18,11 @@ $factory->define(Product::class, function (Faker $faker) { $factory->state(Product::class, 'simple', [ 'type' => 'simple', ]); -$factory->state(Product::class, 'downloadable_with_stock', [ + +$factory->state(Product::class, 'virtual', [ + 'type' => 'virtual', +]); + +$factory->state(Product::class, 'downloadable', [ 'type' => 'downloadable', ]); \ No newline at end of file diff --git a/packages/Webkul/Sales/src/Repositories/DownloadableLinkPurchasedRepository.php b/packages/Webkul/Sales/src/Repositories/DownloadableLinkPurchasedRepository.php index 84715fdbe..ac3a901b5 100644 --- a/packages/Webkul/Sales/src/Repositories/DownloadableLinkPurchasedRepository.php +++ b/packages/Webkul/Sales/src/Repositories/DownloadableLinkPurchasedRepository.php @@ -55,8 +55,9 @@ class DownloadableLinkPurchasedRepository extends Repository */ public function saveLinks($orderItem) { - if (stristr($orderItem->type,'downloadable') === false || ! isset($orderItem->additional['links'])) + if (! $this->isValidDownloadableProduct($orderItem)) { return; + } foreach ($orderItem->additional['links'] as $linkId) { if (! $productDownloadableLink = $this->productDownloadableLinkRepository->find($linkId)) @@ -78,6 +79,19 @@ class DownloadableLinkPurchasedRepository extends Repository } } + /** + * Return true, if ordered item is valid downloadable product with links + * + * @param mixed $orderItem Webkul\Sales\Models\OrderItem; + * @return bool + */ + private function isValidDownloadableProduct($orderItem) : bool { + if (stristr($orderItem->type,'downloadable') !== false && isset($orderItem->additional['links'])) { + return true; + } + return false; + } + /** * @param OrderItem $orderItem * @param string $status diff --git a/packages/Webkul/Shop/src/Http/Controllers/CartController.php b/packages/Webkul/Shop/src/Http/Controllers/CartController.php index 0c6de7e32..28070dd77 100755 --- a/packages/Webkul/Shop/src/Http/Controllers/CartController.php +++ b/packages/Webkul/Shop/src/Http/Controllers/CartController.php @@ -80,7 +80,12 @@ class CartController extends Controller try { $result = Cart::addProduct($id, request()->all()); - if ($result) { + if ($this->onWarningAddingToCart($result)) { + session()->flash('warning', $result['warning']); + return redirect()->back(); + } + + if ($result instanceof Cart) { session()->flash('success', trans('shop::app.checkout.cart.item.success')); if ($customer = auth()->guard('customer')->user()) @@ -88,8 +93,6 @@ class CartController extends Controller if (request()->get('is_buy_now')) return redirect()->route('shop.checkout.onepage.index'); - } else { - session()->flash('warning', trans('shop::app.checkout.cart.item.error-add')); } } catch(\Exception $e) { session()->flash('error', trans($e->getMessage())); @@ -205,4 +208,16 @@ class CartController extends Controller 'message' => trans('shop::app.checkout.total.remove-coupon') ]); } + + /** + * Returns true, if result of adding product to cart + * is an array and contains a key "warning" + * + * @param $result + * + * @return bool + */ + private function onWarningAddingToCart($result): bool { + return is_array($result) && isset($result['warning']); + } } \ No newline at end of file diff --git a/packages/Webkul/Shop/src/Resources/assets/sass/app.scss b/packages/Webkul/Shop/src/Resources/assets/sass/app.scss index 59466f38f..92b2a2e7c 100755 --- a/packages/Webkul/Shop/src/Resources/assets/sass/app.scss +++ b/packages/Webkul/Shop/src/Resources/assets/sass/app.scss @@ -2400,7 +2400,7 @@ section.cart { .control-group { font-size: 16px !important; - margin: 0px; + margin: 0 15px 0 0; width: auto; .wrap { @@ -2422,7 +2422,7 @@ section.cart { .remove, .towishlist { line-height: 35px; - margin-left: 15px; + margin-right: 15px; } } } diff --git a/packages/Webkul/Shop/src/Resources/lang/en/app.php b/packages/Webkul/Shop/src/Resources/lang/en/app.php index 548f18b4c..216d9d717 100755 --- a/packages/Webkul/Shop/src/Resources/lang/en/app.php +++ b/packages/Webkul/Shop/src/Resources/lang/en/app.php @@ -426,7 +426,8 @@ return [ 'missing_fields' => 'Some required fields missing for this product.', 'missing_options' => 'Options are missing for this product.', 'missing_links' => 'Downloadable links are missing for this product.', - 'qty_missing' => 'Atleast one product should have more than 1 quantity.' + 'qty_missing' => 'Atleast one product should have more than 1 quantity.', + 'qty_impossible' => 'Cannot add more than one of these products to cart.' ], 'create-error' => 'Encountered some issue while making cart instance.', 'title' => 'Shopping Cart', diff --git a/packages/Webkul/Shop/src/Resources/views/checkout/cart/index.blade.php b/packages/Webkul/Shop/src/Resources/views/checkout/cart/index.blade.php index 294c0c5b6..f5c66718a 100755 --- a/packages/Webkul/Shop/src/Resources/views/checkout/cart/index.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/checkout/cart/index.blade.php @@ -68,10 +68,12 @@ {!! view_render_event('bagisto.shop.checkout.cart.item.quantity.before', ['item' => $item]) !!}
- - + @if ($item->product->getTypeInstance()->showQuantityBox() === true) + + + @endif {{ __('shop::app.checkout.cart.remove-link') }} @@ -106,9 +108,11 @@ {{ __('shop::app.checkout.cart.continue-shopping') }}
- + @endif @if (! cart()->hasError()) diff --git a/tests/_support/UnitTester.php b/tests/_support/UnitTester.php index e19544a51..5e3dccc40 100644 --- a/tests/_support/UnitTester.php +++ b/tests/_support/UnitTester.php @@ -1,5 +1,6 @@ comment('I execute function "' + . $functionName + . '" of class "' + . (is_object($className) ? get_class($className) : $className) + . '" with ' + . count($methodParams) + . ' method-params, ' + . count($constructParams) + . ' constuctor-params and ' + . count($mocks) + . ' mocked class-methods/params' + ); + $class = new \ReflectionClass($className); + $method = $class->getMethod($functionName); + $method->setAccessible(true); + if (is_object($className)) { + $reflectedClass = $className; + } elseif (empty($constructParams)) { + $reflectedClass = Stub::make($className, $mocks); + } else { + $reflectedClass = Stub::construct($className, $constructParams, $mocks); + } + + return $method->invokeArgs($reflectedClass, $methodParams); + } } diff --git a/tests/functional/Admin/Catalog/ProductCest.php b/tests/functional/Admin/Catalog/ProductCest.php index d666fd90a..9d2d3461a 100644 --- a/tests/functional/Admin/Catalog/ProductCest.php +++ b/tests/functional/Admin/Catalog/ProductCest.php @@ -7,6 +7,7 @@ use Faker\Factory; use Webkul\Attribute\Models\Attribute; use Webkul\Attribute\Models\AttributeFamily; use Webkul\Attribute\Models\AttributeOption; +use Webkul\Core\Helpers\Laravel5Helper; use Webkul\Core\Models\Locale; use Webkul\Product\Models\Product; use Webkul\Product\Models\ProductAttributeValue; @@ -56,7 +57,7 @@ class ProductCest public function testIndex(FunctionalTester $I): void { - $product = $I->haveProduct([], ['simple']); + $product = $I->haveProduct(Laravel5Helper::SIMPLE_PRODUCT, [], ['simple']); $I->loginAsAdmin(); $I->amOnAdminRoute('admin.dashboard.index'); diff --git a/tests/functional/Admin/Customer/ReviewCest.php b/tests/functional/Admin/Customer/ReviewCest.php index bd04f1c81..a2c08e42d 100644 --- a/tests/functional/Admin/Customer/ReviewCest.php +++ b/tests/functional/Admin/Customer/ReviewCest.php @@ -4,6 +4,7 @@ namespace Tests\Functional\Admin\Customer; use FunctionalTester; +use Webkul\Core\Helpers\Laravel5Helper; use Webkul\Product\Models\ProductReview; @@ -11,7 +12,7 @@ class ReviewCest { public function testIndex(FunctionalTester $I): void { - $product = $I->haveProduct([], ['simple']); + $product = $I->haveProduct(Laravel5Helper::SIMPLE_PRODUCT, [], ['simple']); $review = $I->have(ProductReview::class, ['product_id' => $product->id]); $I->loginAsAdmin(); diff --git a/tests/functional/Checkout/Cart/CartCest.php b/tests/functional/Checkout/Cart/CartCest.php new file mode 100644 index 000000000..db20d49f0 --- /dev/null +++ b/tests/functional/Checkout/Cart/CartCest.php @@ -0,0 +1,55 @@ + [], + 'productInventory' => [ + 'qty' => 10, + ], + 'attributeValues' => [ + 'status' => 1, + ], + ]; + $this->productWithQuantityBox = $I->haveProduct(Laravel5Helper::SIMPLE_PRODUCT, $productConfig); + $this->productWithoutQuantityBox = $I->haveProduct(Laravel5Helper::DOWNLOADABLE_PRODUCT, $productConfig); + } + + public function checkCartWithQuantityBox(FunctionalTester $I) + { + Cart::addProduct($this->productWithQuantityBox->id, [ + '_token' => session('_token'), + 'product_id' => $this->productWithQuantityBox->id, + 'quantity' => 1, + ]); + + $I->amOnPage('/checkout/cart'); + $I->seeElement('#update_cart_button'); + } + + public function checkCartWithoutQuantityBox(FunctionalTester $I) + { + Cart::addProduct($this->productWithoutQuantityBox->id, [ + '_token' => session('_token'), + 'product_id' => $this->productWithoutQuantityBox->id, + 'links' => $this->productWithoutQuantityBox->downloadable_links->pluck('id')->all(), + 'quantity' => 1, + ]); + + $I->amOnPage('/checkout/cart'); + $I->dontSeeElement('#update_cart_button'); + } + +} \ No newline at end of file diff --git a/tests/functional/Shop/GuestCheckoutCest.php b/tests/functional/Shop/GuestCheckoutCest.php index ea712b673..e7610265f 100644 --- a/tests/functional/Shop/GuestCheckoutCest.php +++ b/tests/functional/Shop/GuestCheckoutCest.php @@ -6,6 +6,7 @@ use Codeception\Example; use FunctionalTester; use Faker\Factory; use Cart; +use Webkul\Core\Helpers\Laravel5Helper; class GuestCheckoutCest { @@ -34,10 +35,10 @@ class GuestCheckoutCest ], ]; - $this->productNoGuestCheckout = $I->haveProduct($pConfigDefault, ['simple']); + $this->productNoGuestCheckout = $I->haveProduct(Laravel5Helper::SIMPLE_PRODUCT, $pConfigDefault, ['simple']); $this->productNoGuestCheckout->refresh(); - $this->productGuestCheckout = $I->haveProduct($pConfigGuestCheckout, ['simple']); + $this->productGuestCheckout = $I->haveProduct(Laravel5Helper::SIMPLE_PRODUCT, $pConfigGuestCheckout, ['simple']); $this->productGuestCheckout->refresh(); } @@ -61,7 +62,7 @@ class GuestCheckoutCest $I->see($product->name, '//div[@class="product-information"]/div[@class="product-name"]'); $I->click(__('shop::app.products.add-to-cart'), '//form[input[@name="product_id"][@value="' . $product->id . '"]]/button'); - $I->seeInSource(__('shop::app.checkout.cart.item.success')); + $I->amOnRoute('shop.checkout.cart.index'); $I->see('Shopping Cart', '//div[@class="title"]'); $I->makeHtmlSnapshot('guestCheckout_' . $example['globalConfig'] . '_' . $product->getAttribute('guest_checkout')); diff --git a/tests/unit.suite.yml b/tests/unit.suite.yml index 53b2aa210..ba6191f9a 100644 --- a/tests/unit.suite.yml +++ b/tests/unit.suite.yml @@ -8,7 +8,7 @@ modules: - Asserts - Filesystem - \Helper\Unit - - Laravel5: + - Webkul\Core\Helpers\Laravel5Helper: environment_file: .env.testing run_database_migrations: true run_database_seeder: true diff --git a/tests/unit/Checkout/Cart/Controllers/CartControllerCest.php b/tests/unit/Checkout/Cart/Controllers/CartControllerCest.php new file mode 100644 index 000000000..5d05a6ca3 --- /dev/null +++ b/tests/unit/Checkout/Cart/Controllers/CartControllerCest.php @@ -0,0 +1,36 @@ + ['key' => 'value', 'warning' => 'Hello World. Something went wrong.'], + 'expected' => true, + ], + [ + 'result' => ['key' => 'value'], + 'expected' => false, + ], + [ + 'result' => new Cart(), + 'expected' => false, + ], + ]; + + foreach ($scenarios as $scenario) { + $I->assertEquals($scenario['expected'], $I->executeFunction(CartController::class, 'onWarningAddingToCart', [$scenario['result']])); + } + } +} \ No newline at end of file diff --git a/tests/unit/Checkout/Cart/Models/CartModelCest.php b/tests/unit/Checkout/Cart/Models/CartModelCest.php new file mode 100644 index 000000000..effd9b1c9 --- /dev/null +++ b/tests/unit/Checkout/Cart/Models/CartModelCest.php @@ -0,0 +1,63 @@ +faker = Factory::create(); + + $this->sessionToken = $this->faker->uuid; + session(['_token' => $this->sessionToken]); + + $productConfig = [ + 'productAttributes' => [], + 'productInventory' => [ + 'qty' => 10, + ], + 'attributeValues' => [ + 'status' => 1, + ], + ]; + $this->productWithQuantityBox = $I->haveProduct(Laravel5Helper::SIMPLE_PRODUCT, $productConfig); + + $this->productWithoutQuantityBox = $I->haveProduct(Laravel5Helper::DOWNLOADABLE_PRODUCT, $productConfig); + } + + public function testHasProductsWithQuantityBox(UnitTester $I) + { + $I->wantTo('check function with cart, that contains a product with QuantityBox() == false'); + $this->cart = Cart::addProduct($this->productWithoutQuantityBox->id, [ + '_token' => session('_token'), + 'product_id' => $this->productWithoutQuantityBox->id, + 'links' => $this->productWithoutQuantityBox->downloadable_links->pluck('id')->all(), + 'quantity' => 1, + ]); + $cartItemIdOfProductWithoutQuantityBox = $this->cart->items[0]->id; + $I->assertFalse(Cart::getCart()->hasProductsWithQuantityBox()); + + $I->wantTo('check function with cart, that is mixed'); + Cart::addProduct($this->productWithQuantityBox->id, [ + '_token' => session('_token'), + 'product_id' => $this->productWithQuantityBox->id, + 'quantity' => 1, + ]); + $I->assertTrue(Cart::getCart()->hasProductsWithQuantityBox()); + + $I->wantTo('check function with cart, that contains a product with QuantityBox() == true'); + Cart::removeItem($cartItemIdOfProductWithoutQuantityBox); + $I->assertTrue(Cart::getCart()->hasProductsWithQuantityBox()); + } +} \ No newline at end of file