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/blije-gasten.komma.pro/app/Komma/Shop/Tests/Browser/CheckoutTest.php
<?php

namespace App\Komma\Shop\Tests\Browser;

use App\Komma\Addresses\Models\Address;
use App\Komma\Globalization\RegionInfo;
use App\Komma\Globalization\RegionInfoInterface;
use App\Komma\Kms\QualityAssurance\ExtraDuskTools;
use App\Komma\Shop\Cart\ShoppingCartService;
use App\Komma\Shop\Orders\Models\Order;
use App\Komma\Shop\Orders\OrderStatus;
use App\Komma\Shop\Orders\Product\OrderedProduct;
use App\Komma\Shop\Orders\ProductComposite\OrderedProductComposite;
use App\Komma\Shop\Orders\ProductGroup\OrderedProductGroup;
use App\Komma\Shop\Payment\TransactionStatus;
use App\Komma\Shop\Products\Product\Product;
use App\Komma\Shop\Products\ProductComposite\ProductComposite;
use App\Komma\Shop\Products\ProductGroup\ProductGroup;
use App\Komma\Shop\Tests\Browser\Pages\ShoppingCartTestPage;
use App\Komma\Shop\Tests\DuskTestCase;
use App\Komma\Shop\Vat\Models\Rate;
use App\Komma\Users\Models\SiteUser;
use Illuminate\Database\Eloquent\Collection;
use Laravel\Dusk\Browser;

class CheckoutTest extends DuskTestCase
{
//    use DatabaseTransactions; //Automatically rolls back database actions after tests. Note: when you enable this, assertProductVisible creates a user but cannot be logged in somehow. Laravel dusk problem i think.
    /**
     * @group Checkout
     * @test
     * @throws \Throwable
     */
    public function assertCartEmpty()
    {
        $shoppingCartService = new ShoppingCartService();
        $shoppingCartService->clear(); //Clear the cart if it not already was
        $regionInfo = app(RegionInfoInterface::class);

        $counter = 0;
        $this->browse(function (Browser $browser) use($regionInfo) {
            $browser->loginAs(SiteUser::find(1), 'site')
                ->visit(new ShoppingCartTestPage())
                ->assertSee(__('shop/cart.cart'))
                ->assertSeeIn('@subtotal', $regionInfo->getCurrencySymbol().' 0');
        });
    }

    /**
     * Test coupon codes in checkout
     *
     * @group Checkout
     * @test
     * @throws \Throwable
     */
    public function testCouponAndVat()
    {
        /** @var SiteUser $user */
        $user = factory(SiteUser::class)->create();
        /** @var Address $address */
        $address = factory(Address::class)->create();
        $user->addresses()->save($address);

        $this->assertDatabaseHas('site_users', [
            'id' => $user->id
        ]);

        $product = Product::find(1);
        $regionInfo = app(RegionInfoInterface::class);

        $this->browse(function (Browser $browser) use($user, $product, $address, $regionInfo) {
            $browser->logout('site'); //Make sure we dont have a session
            $browser->loginAs($user->id, 'site')
                ->visit(new ShoppingCartTestPage())
                ->click('@addProductWithId1')
                ->waitUntil('document.querySelector(\'[dusk="shoppingCartItemList"]\').childElementCount == 1')
                ->click('@checkout')
                ->assertSee(__('shop/checkout.invoice_address'))
                ->assertSee(__('shop/checkout.shipping_address'))
                ->scrollToElement('[dusk="checkout"]') //See extra dusk tools
                ->assertVisible('[dusk="checkout"]')
                ->assertSee(__('shop/checkout.agree_to_terms'))
                ->type('@coupon_code', 'Absolute5') //Add 5 euro discount
                ->click('@add_coupon')
                ->pause(100)
                ->scrollToElement('[dusk="Absolute5"]') //See extra dusk tools
                ->assertVisible('[dusk="Absolute5"]')
                ->select('shipping_country', 'GBR')->pause(150)
                //The product is added 10 times thanks to cart.js addProductToShoppingcart method. 500 is 500 cents from Absolute5 coupon. And 1499 is the shipping costs of GBR
                ->assertSee($regionInfo->getNumberFormat()->centsToCurrency($product->getTotal() * 10))
                ->assertSee($regionInfo->getNumberFormat()->centsToCurrency(round((((($product->getTotal() * 10) + 1499) - 500) * 0.21))));
        });
    }

    /**
     * @group Checkout
     * @test
     * @see ExtraDuskTools
     * @throws \Throwable
     */
    public function assertCartNotEmptyWhenRandomProductAdded()
    {
        $shoppingCartService = new ShoppingCartService();
        $shoppingCartService->clear(); //Clear the cart if it not already was
        $regionInfo = app(RegionInfoInterface::class);

        $this->browse(function (Browser $browser) use($regionInfo, $shoppingCartService) {
            $browser->loginAs(SiteUser::find(1), 'site');
                $browser->visit(new ShoppingCartTestPage())
                ->assertSee(__('shop/cart.cart'))
                ->pause(500)
                ->assertSeeIn('@subtotal', $regionInfo->getCurrencySymbol().' 0')
                ->waitFor('@addRandomProduct')
                ->waitUntil('document.readyState === "complete"')->pause(500) //Also wait till javascript is loaded completely.
                ->click('@addRandomProduct')
                ->waitUntil('document.querySelectorAll(\'[dusk="shoppingCartItemList"] > li\').length === 1') //Wait until one item is visible in the list of shopping cart items
                ->assertDontSeeIn('@subtotal', $regionInfo->getCurrencySymbol().' 0');
        });
    }

    /**
     * Test a successful checkout with payment
     *
     * @group Checkout
     * @test
     * @throws \Throwable
     */
    public function testCheckoutForm()
    {
        /** @var SiteUser $user */
        $user = factory(SiteUser::class)->create();
        /** @var Address $address */
        $address = factory(Address::class)->create();
        $user->addresses()->save($address);

        $this->assertDatabaseHas('site_users', [
           'id' => $user->id
        ]);

        $regionInfo = app(RegionInfoInterface::class);
        $product = Product::find(1);

        $this->browse(function (Browser $browser) use($user, $product, $regionInfo, $address) {
            $browser->loginAs($user->id, 'site')
                ->visit(new ShoppingCartTestPage())
                ->click('@addProductWithId1')
                ->waitForReload()
                ->click('@checkout')
                ->assertSee(__('shop/checkout.invoice_address'))
                ->assertSee(__('shop/checkout.shipping_address'))
                ->scrollToElement('[dusk="checkout"]') //See extra dusk tools
                ->assertVisible('[dusk="checkout"]')
                ->assertSee(__('shop/checkout.agree_to_terms'))
                ->assertRadioSelected('@new_invoice_address', '-1') //-1 Means that the backend could see that this is a new address instead of an existing one (bigger as 0 value);
                ->assertRadioSelected('@new_shipping_address', '-1')
                ->type('@invoice_street', $address->street)
                ->type('@invoice_house_number', $address->house_number)
                ->type('@invoice_postal_code', $address->postal_code)
                ->type('@invoice_city', $address->city)
                ->type('@invoice_phone', $address->telephone)
                ->select('@invoice_country', $address->country_iso3)
                ->type('@shipping_street', $address->street)
                ->type('@shipping_house_number', $address->house_number)
                ->type('@shipping_postal_code', $address->postal_code)
                ->type('@shipping_city', $address->city)
                ->type('@shipping_phone', $address->telephone)
                ->select('@shipping_country', $address->country_iso3)
                ->type('@remarks', 'None')
                ->assertInputValue('@invoice_street', $address->street)
                ->assertInputValue('@invoice_house_number', $address->house_number)
                ->assertInputValue('@invoice_postal_code', $address->postal_code)
                ->assertInputValue('@invoice_city', $address->city)
                ->assertInputValue('@invoice_phone', $address->telephone)
                ->assertSelected('@invoice_country', $address->country_iso3)
                ->assertInputValue('@shipping_street', $address->street)
                ->assertInputValue('@shipping_house_number', $address->house_number)
                ->assertInputValue('@shipping_postal_code', $address->postal_code)
                ->assertInputValue('@shipping_city', $address->city)
                ->assertInputValue('@shipping_phone', $address->telephone)
                ->assertSelected('@shipping_country', $address->country_iso3)
                ->assertInputValue('@remarks', 'None')
                ->assertSee($product->getDisplayName());

                $browser->driver->executeScript('window.scrollTo(0,document.body.scrollHeight);'); //Scroll to bottom

                $browser
                ->check('@terms_and_conditions')
                ->click('@checkout')
                ->pause(500)
                ->assertSee('Welkom bij KommaPSP')
                ->select('@payment_status', TransactionStatus::PAYMENT_PAID)
                ->click('@redir') //Pay
                ->assertSee('We have received your payment')
                ->assertSee(TransactionStatus::PAYMENT_PAID)
                ->assertSee(OrderStatus::AWAITING_FULFILLMENT);
        });
    }

    /**
     * Test a successful checkout with payment
     *
     * @group Checkout
     * @test
     * @throws \Throwable
     */
    public function testInvalidCheckoutForm()
    {
        /** @var SiteUser $user */
        $user = factory(SiteUser::class)->create();
        /** @var Address $address */
        $address = factory(Address::class)->create();
        $user->addresses()->save($address);

        $this->assertDatabaseHas('site_users', [
            'id' => $user->id
        ]);

        $regionInfo = app(RegionInfoInterface::class);
        $product = Product::find(1);

        $this->browse(function (Browser $browser) use($user, $product, $regionInfo, $address) {
            $browser->loginAs($user->id, 'site')
                ->visit(new ShoppingCartTestPage())
                ->click('@addProductWithId1')
                ->waitForReload()
                ->click('@checkout')
                ->assertSee(__('shop/checkout.invoice_address'))
                ->assertSee(__('shop/checkout.shipping_address'))
                ->scrollToElement('[dusk="checkout"]') //See extra dusk tools
                ->assertVisible('[dusk="checkout"]')
                ->assertSee(__('shop/checkout.agree_to_terms'))
                ->assertRadioSelected('@new_invoice_address', '-1') //-1 Means that the backend could see that this is a new address instead of an existing one (bigger as 0 value);
                ->assertRadioSelected('@new_shipping_address', '-1')
                ->pause(10)
                ->assertSee($product->getDisplayName());

            $browser->driver->executeScript('window.scrollTo(0,document.body.scrollHeight);'); //Scroll to bottom

            $browser->pause(10)
                ->click('@checkout')
                ->pause(250);

            foreach(['shipping', 'invoice'] as $type) {
                foreach([
                    $type.'_street',
                    $type.'_house_number',
                    $type.'_postal_code',
                    $type.'_city',
                    $type.'_phone',
                ] as $attribute) {
                    $browser->assertSee(__('shop/checkout.validation.required_if', ['attribute' => __('validation.attributes.'.$attribute)]));
                }
            }

        });
    }

    /**
     * Test thanks for order mail contents
     *
     * @group Checkout
     * @test
     * @throws \Throwable
     */
    public function testThanksForOrderMailContents()
    {
        $orderStatus = OrderStatus::PENDING;
        /** @var Order $order */
        $order = Order::inRandomOrder()->first();
        $orderedProductComposites = $order->orderedProductComposites()->get();
        $orderedProductGroups = $order->orderedGroups()->get();
        $orderedProducts = $order->orderedProducts()->get();
        $self = $this;

        $route = route('preview.mail.order_status', ['status' => $orderStatus, 'staffOrCustomer' => 'customer', 'order' => $order->id]); //Thanks for your order mail

        $this->browse(function (Browser $browser) use($route, $orderStatus, $order, $orderedProducts, $orderedProductGroups, $orderedProductComposites, $self) {
            $browser->visit($route)
                //Assert general texts
                ->assertSee(__('shop/orders.mail.'.$orderStatus.'.customer.body'))
                ->assertSee(__('shop/orders.mail.'.$orderStatus.'.customer.button_text'))
                ->assertSee(__('shop/orders.mail.'.$orderStatus.'.customer.closure'))
                ->assertSee(config('site.company.name'));

                $self->assertProductableNamesVisible($browser, $orderedProducts);
                $self->assertProductableNamesVisible($browser, $orderedProductGroups);
                $self->assertProductableNamesVisible($browser, $orderedProductComposites);
        });
    }

    /**
     * Test the contents of the mail that is sent to the customer and staff
     * when he completed the payment
     *
     * @group Checkout
     * @test
     * @throws \Throwable
     */
    public function testCustomerPaidMailToCustomerAndStaff()
    {
        $orderStatus = OrderStatus::AWAITING_FULFILLMENT;
        /** @var Order $order */
        $order = Order::inRandomOrder()->first();
        $orderedProductComposites = $order->orderedProductComposites()->get();
        $orderedProductGroups = $order->orderedGroups()->get();
        $orderedProducts = $order->orderedProducts()->get();
        $self = $this;

        foreach(['customer', 'staff'] as $type) {
            $route = route('preview.mail.order_status', ['status' => $orderStatus, 'staffOrCustomer' => $type, 'order' => $order->id]); //Thanks for your order mail

            $this->browse(function (Browser $browser) use($route, $orderStatus, $type, $order, $orderedProducts, $orderedProductGroups, $orderedProductComposites, $self) {
                $browser->visit($route)
                    //Assert general text
                    ->assertSee(__('shop/orders.mail.'.$orderStatus.'.'.$type.'.body'))
                    ->assertSee(__('shop/orders.mail.'.$orderStatus.'.'.$type.'.button_text'))
                    ->assertSee(__('shop/orders.mail.'.$orderStatus.'.'.$type.'.closure'))
                    ->assertSee(config('site.company.name'));

                    $self->assertProductableNamesVisible($browser, $orderedProducts);
                    $self->assertProductableNamesVisible($browser, $orderedProductGroups);
                    $self->assertProductableNamesVisible($browser, $orderedProductComposites);
            });
        }
    }

    /**
     * Helper function that tests if it can see a productable
     *
     * @param Browser $browser
     * @param Collection $orderedProductableCollection
     */
    private function assertProductableNamesVisible(Browser $browser, Collection $orderedProductableCollection)
    {
        foreach($orderedProductableCollection as $orderedProductable)
        {
            $name = '';
            switch (get_class($orderedProductable))
            {
                case OrderedProduct::class:
                    /** @var OrderedProduct $orderedProductable */
                    $product = $orderedProductable->product()->first();
                    /** @var Product $name */
                    $name = $product->getDisplayName();
                    break;
                case OrderedProductGroup::class:
                    /** @var OrderedProductGroup $orderedProductable */
                    $productGroup = $orderedProductable->productGroup()->first();
                    /** @var ProductGroup $productGroup */
                    $name = $productGroup->getDisplayName();
                    break;
                case OrderedProductComposite::class:
                    /** @var OrderedProductComposite $orderedProductable */
                    $orderedProductable = $orderedProductable->productComposite()->first();
                    /** @var ProductComposite $orderedProductable */
                    $name = $orderedProductable->getDisplayName();
                    break;
                default:
                    return;
            }

            if($name != '') $browser->assertSee($name);
        }
    }
}