From 31ad898f52d5dcec07a45658f218df7e435170c7 Mon Sep 17 00:00:00 2001 From: Steffen Mahler Date: Thu, 6 Aug 2020 16:15:42 +0200 Subject: [PATCH] fix issue in booking product, refactoring of cart.php, adding test for cart.php --- .../Factories/BookingProductFactory.php | 4 +- .../BookingProduct/src/Type/Booking.php | 15 +- packages/Webkul/Checkout/src/Cart.php | 60 +---- tests/unit/Checkout/CartCest.php | 239 ++++++++++++++++++ 4 files changed, 252 insertions(+), 66 deletions(-) create mode 100644 tests/unit/Checkout/CartCest.php diff --git a/packages/Webkul/BookingProduct/src/Database/Factories/BookingProductFactory.php b/packages/Webkul/BookingProduct/src/Database/Factories/BookingProductFactory.php index 3b74a8a1f..738d0e8a3 100644 --- a/packages/Webkul/BookingProduct/src/Database/Factories/BookingProductFactory.php +++ b/packages/Webkul/BookingProduct/src/Database/Factories/BookingProductFactory.php @@ -8,8 +8,10 @@ use Webkul\BookingProduct\Models\BookingProduct; use Webkul\Product\Models\Product; $factory->define(BookingProduct::class, function (Faker $faker, array $attributes) { + $bookingTypes = ['event']; + return [ - 'type' => array_rand(['event']), + 'type' => $bookingTypes[array_rand(['event'])], 'qty' => $faker->randomNumber(2), 'available_from' => Carbon::yesterday(), 'available_to' => Carbon::tomorrow(), diff --git a/packages/Webkul/BookingProduct/src/Type/Booking.php b/packages/Webkul/BookingProduct/src/Type/Booking.php index bc5c55485..a6184a6dc 100644 --- a/packages/Webkul/BookingProduct/src/Type/Booking.php +++ b/packages/Webkul/BookingProduct/src/Type/Booking.php @@ -133,7 +133,7 @@ class Booking extends Virtual if (! $bookingProduct) { return false; } - + if (in_array($bookingProduct->type, ['default', 'rental', 'table'])) { return true; } @@ -180,7 +180,7 @@ class Booking extends Virtual if ($bookingProduct->type == 'event') { if (Carbon::now() > $bookingProduct->available_from && Carbon::now() > $bookingProduct->available_to) { return trans('shop::app.checkout.cart.event.expired'); - } + } $filtered = Arr::where($data['booking']['qty'], function ($qty, $key) { return $qty != 0; @@ -195,18 +195,13 @@ class Booking extends Virtual continue; } - $cartProducts = parent::prepareForCart(array_merge($data, [ - 'product_id' => $data['product_id'], - 'quantity' => $qty, - 'booking' => [ - 'ticket_id' => $ticketId, - ], - ])); + $data['booking']['ticket_id'] = $ticketId; + $cartProducts = parent::prepareForCart($data); if (is_string($cartProducts)) { return $cartProducts; } - + $products = array_merge($products, $cartProducts); } } else { diff --git a/packages/Webkul/Checkout/src/Cart.php b/packages/Webkul/Checkout/src/Cart.php index 5ff87a498..d337181f9 100755 --- a/packages/Webkul/Checkout/src/Cart.php +++ b/packages/Webkul/Checkout/src/Cart.php @@ -335,9 +335,9 @@ class Cart /** * This function handles when guest has some of cart products and then logs in. * - * @return bool + * @return void */ - public function mergeCart() + public function mergeCart(): void { if (session()->has('cart')) { $cart = $this->cartRepository->findOneWhere([ @@ -359,59 +359,11 @@ class Cart session()->forget('cart'); - return true; + return; } - foreach ($guestCart->items as $key => $guestCartItem) { - $found = false; - - foreach ($cart->items as $cartItem) { - if (! $cartItem - ->product - ->getTypeInstance() - ->compareOptions($cartItem->additional, $guestCartItem->additional) - ) { - continue; - } - - $found = true; - - $cartItem->quantity = $newQuantity = $cartItem->quantity + $guestCartItem->quantity; - - if ($cartItem->quantity > $cartItem->product->getTypeInstance()->totalQuantity()) { - $cartItem->quantity = $newQuantity = $cartItem->product->getTypeInstance()->totalQuantity(); - } - - if (! $this->isItemHaveQuantity($cartItem)) { - $this->cartItemRepository->delete($guestCartItem->id); - - continue; - } - - $this->cartItemRepository->update([ - 'quantity' => $newQuantity, - 'total' => core()->convertPrice($cartItem->price * $newQuantity), - 'base_total' => $cartItem->price * $newQuantity, - 'total_weight' => $cartItem->weight * $newQuantity, - 'base_total_weight' => $cartItem->weight * $newQuantity, - ], $cartItem->id); - - $guestCart->items->forget($key); - - $this->cartItemRepository->delete($guestCartItem->id); - } - - if (! $found) { - $this->cartItemRepository->update([ - 'cart_id' => $cart->id, - ], $guestCartItem->id); - - foreach ($guestCartItem->children as $child) { - $this->cartItemRepository->update([ - 'cart_id' => $cart->id, - ], $child->id); - } - } + foreach ($guestCart->items as $guestCartItem) { + $this->addProduct($guestCartItem->product_id, $guestCartItem->additional); } $this->collectTotals(); @@ -420,8 +372,6 @@ class Cart session()->forget('cart'); } - - return true; } /** diff --git a/tests/unit/Checkout/CartCest.php b/tests/unit/Checkout/CartCest.php new file mode 100644 index 000000000..9a1e2283c --- /dev/null +++ b/tests/unit/Checkout/CartCest.php @@ -0,0 +1,239 @@ +createProducts($I); + + $scenarios = $this->getMergeCartScenarios(); + + foreach ($scenarios as $scenario) { + $I->comment("Check, I'm a guest"); + $I->assertFalse(auth()->guard('customer')->check()); + + $data = [ + '_token' => session('_token'), + 'quantity' => 1, + 'product_id' => $scenario['products'][0]['product']->id, + ]; + $data = array_merge($data, $scenario['products'][0]['data']); + + $I->comment('A guest is adding a first product to cart'); + cart()->addProduct($scenario['products'][0]['product']->id, $data); + $I->assertEquals(1, cart()->getCart()->items->count()); + + $I->comment('Guest is logging in...then guest is a known customer.'); + auth()->guard('customer')->onceUsingId($this->customer->id); + Event::dispatch('customer.after.login', $this->customer['email']); + $I->comment("Let us assume that the customer's shopping cart was empty. The individual product from the guest's shopping cart is transferred to the customer's shopping cart."); + $I->assertEquals(1, cart()->getCart()->items->count()); + + auth()->guard('customer')->logout(); + $data = [ + '_token' => session('_token'), + 'quantity' => 1, + 'product_id' => $scenario['products'][1]['product']->id, + ]; + $data = array_merge($data, $scenario['products'][1]['data']); + + $I->comment('Again, guest is adding a ' . $scenario['product_type'] . ' product to cart.'); + cart()->addProduct($scenario['products'][1]['product']->id, $data); + $I->assertEquals(1, cart()->getCart()->items->count()); + + $I->comment('And will be logged in.'); + auth()->guard('customer')->onceUsingId($this->customer->id); + + Event::dispatch('customer.after.login', $this->customer['email']); + $I->assertEquals($scenario['results']['cart_items_count'], cart()->getCart()->items->count()); + + auth()->guard('customer')->logout(); + $data = [ + '_token' => session('_token'), + 'quantity' => 2, + 'product_id' => $scenario['products'][0]['product']->id, + ]; + $data = array_merge($data, $scenario['products'][0]['data']); + + $I->comment('Again, guest is adding first ' . $scenario['product_type'] . ' product again.'); + cart()->addProduct($scenario['products'][0]['product']->id, $data); + $I->assertEquals(1, cart()->getCart()->items->count()); + $I->assertEquals(2, cart()->getCart()->items_qty); + + $I->comment('And will be logged in.'); + auth()->guard('customer')->onceUsingId($this->customer->id); + + Event::dispatch('customer.after.login', $this->customer['email']); + $I->assertEquals($scenario['results']['cart_items_count'], cart()->getCart()->items->count()); + $I->assertEquals($scenario['results']['cart_items_quantity'], cart()->getCart()->items_qty); + + $this->cleanUp(); + $I->comment('=== ' . $scenario['product_type'] . ' DONE ==='); + } + } + + private function getMergeCartScenarios(): array + { + return [ + [ + 'product_type' => 'simple', + 'products' => [ + [ + 'product' => $this->simple1, + 'data' => [], + ], + [ + 'product' => $this->simple2, + 'data' => [], + ], + ], + 'results' => [ + 'cart_items_count' => 2, + 'cart_items_quantity' => 4, + ], + ], + [ + 'product_type' => 'virtual', + 'products' => [ + [ + 'product' => $this->virtual1, + 'data' => [], + ], + [ + 'product' => $this->virtual2, + 'data' => [], + ], + ], + 'results' => [ + 'cart_items_count' => 2, + 'cart_items_quantity' => 4, + ], + ], + [ + 'product_type' => 'downloadable', + 'products' => [ + [ + 'product' => $this->downloadable1, + 'data' => [ + 'links' => [$this->downloadableLinkId1], + ], + ], + [ + 'product' => $this->downloadable2, + 'data' => [ + 'links' => [$this->downloadableLinkId2], + ], + ], + ], + 'results' => [ + 'cart_items_count' => 2, + 'cart_items_quantity' => 4, + ], + ], + [ + 'product_type' => 'booking', + 'products' => [ + [ + 'product' => $this->booking1, + 'data' => [ + 'booking' => [ + 'qty' => [ + $this->bookingTicket1->id => 1, + ], + ], + ], + ], + [ + 'product' => $this->booking2, + 'data' => [ + 'booking' => [ + 'qty' => [ + $this->bookingTicket2->id => 1, + ], + ], + ], + ], + ], + 'results' => [ + 'cart_items_count' => 2, + 'cart_items_quantity' => 4, + ], + ], + ]; + } + + private function createProducts(UnitTester $I) + { + $this->customer = $I->have(Customer::class); + + $this->simple1 = $I->haveProduct(Laravel5Helper::SIMPLE_PRODUCT, []); + $this->simple2 = $I->haveProduct(Laravel5Helper::SIMPLE_PRODUCT, []); + + $this->virtual1 = $I->haveProduct(Laravel5Helper::VIRTUAL_PRODUCT, []); + $this->virtual2 = $I->haveProduct(Laravel5Helper::VIRTUAL_PRODUCT, []); + + $this->downloadable1 = $I->haveProduct(Laravel5Helper::DOWNLOADABLE_PRODUCT, []); + $this->downloadableLinkId1 = $I->grabRecord( + 'product_downloadable_links', + [ + 'product_id' => $this->downloadable1->id, + ] + )['id']; + + $this->downloadable2 = $I->haveProduct(Laravel5Helper::DOWNLOADABLE_PRODUCT, []); + $this->downloadableLinkId2 = $I->grabRecord( + 'product_downloadable_links', + [ + 'product_id' => $this->downloadable2->id, + ] + )['id']; + + $this->booking1 = $I->haveProduct(Laravel5Helper::BOOKING_EVENT_PRODUCT, []); + $bookingProduct1 = BookingProduct::query()->where('product_id', $this->booking1->id)->firstOrFail(); + $this->bookingTicket1 = BookingProductEventTicket::query()->where('booking_product_id', $bookingProduct1->id)->firstOrFail(); + + $this->booking2 = $I->haveProduct(Laravel5Helper::BOOKING_EVENT_PRODUCT, []); + $bookingProduct2 = BookingProduct::query()->where('product_id', $this->booking2->id)->firstOrFail(); + $this->bookingTicket2 = BookingProductEventTicket::query()->where('booking_product_id', $bookingProduct2->id)->firstOrFail(); + } + + private function cleanUp(): void + { + $cart = cart()->getCart(); + + if ($cart) { + foreach ($cart->items as $item) { + cart()->removeItem($item->id); + } + } + + session()->forget('cart'); + + auth()->guard('customer')->logout(); + + session()->forget('cart'); + } +} \ No newline at end of file