HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers10/ehbo.today/app/KommaApp/Shop/Tests/Unit/CheckoutTest.php
<?php

namespace App\KommaApp\Shop\Tests\Unit;

use App\KommaApp\Shop\Cart\ShoppingCartService;
use App\KommaApp\Shop\Checkout\CheckoutServiceInterface;
use App\KommaApp\Shop\Orders\Kms\OrderMailServiceInterface;
use App\KommaApp\Shop\Orders\Mail\OrderStatusUpdatedCustomer;
use App\KommaApp\Shop\Orders\Mail\OrderStatusUpdatedStaff;
use App\KommaApp\Shop\Orders\Models\Order;
use App\KommaApp\Shop\Orders\Product\OrderedProduct;
use App\KommaApp\Shop\Orders\ProductComposite\OrderedProductComposite;
use App\KommaApp\Shop\Orders\ProductGroup\OrderedProductGroup;
use App\KommaApp\Shop\Products\Product\Product;
use App\KommaApp\Shop\Products\ProductableInterface;
use App\KommaApp\Shop\Products\ProductComposite\ProductComposite;
use App\KommaApp\Shop\Products\ProductGroup\ProductGroup;
use App\KommaApp\Shop\Tests\TestCase;
use App\KommaApp\Sites\Models\Site;
use App\KommaApp\Sites\SiteServiceInterface;
use App\KommaApp\Users\Models\Role;
use App\KommaApp\Users\Models\User;
use App\KommaApp\Users\Roles;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Mail\Mailable;
use Illuminate\Support\Facades\Mail;

class CheckoutTest extends TestCase
{
    use DatabaseTransactions; //Automatically rolls back database actions after tests

    /** @var ShoppingCartService $shoppingCart */
    private $shoppingCart;

    /** @var CheckoutServiceInterface $checkoutService */
    private $checkoutService;

    /** @var OrderMailServiceInterface $orderMailService */
    private $orderMailService;

    /**
     * Runs before each test
     */
    public function setup()
    {
        parent::setup();

        /** @var SiteServiceInterface $siteService */
        $siteService = \App::make(SiteServiceInterface::class); //Singleton
        $siteService->setCurrentSiteToDefault();

        $this->shoppingCart = new ShoppingCartService();
        $this->checkoutService = \App::make(CheckoutServiceInterface::class);
        $this->orderMailService = \App::make(OrderMailServiceInterface::class);
    }

    /**
     * Runs after each test
     */
    public function teardown()
    {
        parent::tearDown();
    }

    /**
     * @test
     * @group Checkout
     * @throws \Throwable
     */
    public function testCheckoutOrderCreationProcessWithProductables()
    {
        //Get a random customer user to test with
        $customer = User::where('role_id', '=', Roles::Customer)->first();
        $this->assertInstanceOf(User::class, $customer);

        //Put some random products in the shopping cart
        $products = Product::inRandomOrder()->take(3)->get();
        $this->assertCount(3, $products);

        //Put some random product groups in the shopping cart
        $productGroups = ProductGroup::inRandomOrder()->take(2)->get();
        $this->assertCount(2, $productGroups);

        //Put some random product composites in the shopping cart
        $productComposites = ProductComposite::inRandomOrder()->take(1)->get();
        $this->assertCount(1, $productComposites);

        //Build an order
        $products->merge($productGroups)->merge($productComposites)->each(function(ProductableInterface $productable) {
           $this->shoppingCart->addProductable($productable, mt_rand(1, 3));
        });

        $order = $this->checkoutService->createOrderFromShoppingCartItemsForCustomer($this->shoppingCart->getItems(), $customer);
        $this->assertInstanceOf(Order::class, $order);

        //Check that the created order is related to the customer and vice versa
        $this->assertEquals($order->customer()->first()->id, $customer->id);
        $orderFromCustomer = $customer->orders()->where('id', '=', $order->id)->first();
        $this->assertEquals($order->id, $orderFromCustomer->id);

        //Check that the product ids are in the orderedProduct product id's
        $ids = $products->pluck('id');
        $orderedProductProductIds = $order->orderedProducts()->with('product')->get()->map(function(OrderedProduct $orderOrderedProduct) use ($ids) {
            return $orderOrderedProduct->product->id;
        });
        $ids->each(function(int $id) use ($orderedProductProductIds) {
            $this->assertNotFalse($orderedProductProductIds->search($id)); //Check that the product id is in the collection of OrderedProduct product ids
        });

        //Check that the product group ids are in the orderedProductGroups productgroup id's
        $ids = $productGroups->pluck('id');
        $orderedProductGroupIds = $order->orderedProductGroups()->with('productGroup')->get()->map(function(OrderedProductGroup $orderOrderedProductGroup) use ($ids) {
            return $orderOrderedProductGroup->productGroup->id;
        });
        $ids->each(function(int $id) use ($orderedProductGroupIds) {
            $this->assertNotFalse($orderedProductGroupIds->search($id)); //Check that the productGroupId is in the collection of OrderedProductGroup ids
        });

        //Check that the product composite ids are in the orderedProductComposite productComposite id's
        $ids = $productComposites->pluck('id');
        $orderedProductCompositeIds = $order->orderedProductComposites()->with('productComposite')->get()->map(function(OrderedProductComposite $orderOrderedProductComposite) use ($ids) {
            return $orderOrderedProductComposite->productComposite->id;
        });
        $ids->each(function(int $id) use ($orderedProductCompositeIds) {
            $this->assertNotFalse($orderedProductCompositeIds->search($id)); //Check that the productGroupId is in the collection of OrderedProductGroup ids
        });

        //Check if customers attributes are in the order itself (to preserve history)
        $this->assertEquals($customer->first_name, $order->invoice_first_name);
        $this->assertEquals($customer->last_name, $order->invoice_last_name);
        $this->assertEquals($customer->email, $order->invoice_email);
        $this->assertEquals($customer->company_name, $order->invoice_company);
        $this->assertEquals($customer->country, $order->invoice_country);
        $this->assertEquals($customer->postal_code, $order->invoice_postal_code);
        $this->assertEquals($customer->city, $order->invoice_city);
        $this->assertEquals($customer->street, $order->invoice_street);
        $this->assertEquals($customer->house_number, $order->invoice_house_number);
        $this->assertEquals($customer->telephone, $order->invoice_telephone);

        $this->assertEquals($customer->first_name, $order->shipping_first_name);
        $this->assertEquals($customer->last_name, $order->shipping_last_name);
        $this->assertEquals($customer->email, $order->shipping_email);
        $this->assertEquals($customer->company_name, $order->shipping_company);
        $this->assertEquals($customer->country, $order->shipping_country);
        $this->assertEquals($customer->postal_code, $order->shipping_postal_code);
        $this->assertEquals($customer->city, $order->shipping_city);
        $this->assertEquals($customer->street, $order->shipping_street);
        $this->assertEquals($customer->house_number, $order->shipping_house_number);
        $this->assertEquals($customer->telephone, $order->shipping_telephone);
    }

    /**
     * @test
     * @group Checkout
     * @throws \Throwable
     */
    public function testCheckoutMails()
    {
        Mail::fake();

        $customer = User::where('role_id', '=', Roles::Member)->first();
        $staff = User::whereIn('role_id', [Roles::SuperAdmin, Roles::Admin])->get();

        $this->shoppingCart->addProductable(ProductComposite::inRandomOrder()->take(1)->first());

        $order = $this->checkoutService->createOrderFromShoppingCartItemsForCustomer($this->shoppingCart->getItems(), $customer);

        $this->orderMailService->mailStaffAboutCurrentOrderStatus($order);
        $staffEmails = $staff->pluck('email');

        Mail::assertQueued(OrderStatusUpdatedStaff::class, function (Mailable $mail) use ($staffEmails){
            $found = false;
            foreach($staffEmails as $staffEmail)
            {
                if($mail->hasTo($staffEmail)) {
                    $found = true;
                    break;
                }
            }

            echo 'An OrderStatusUpdatedStaff mail '.(($found) ? 'was': 'was not').' queued for a staff member with e-mail: '.$staffEmail.PHP_EOL;
            return $found;
        });

        $this->orderMailService->mailCustomerAboutCurrentOrderStatus($order, $customer);


        Mail::assertQueued(OrderStatusUpdatedCustomer::class, function (Mailable $mail) use ($customer){
            $found = $mail->hasTo($customer->email);
            echo 'An OrderStatusUpdatedCustomer mail '.(($found) ? 'was': 'was not').' queued for a customer with e-mail: '.$customer->email.PHP_EOL;
            return $found;
        });
    }
}