first commit

This commit is contained in:
2025-08-02 16:30:27 +02:00
commit 23646bfcee
14851 changed files with 1750626 additions and 0 deletions

View File

@@ -0,0 +1,619 @@
<?php
use Heureka\ShopCertification;
use KupShop\DevelopmentBundle\Util\Tests\CartTestTrait;
use KupShop\DevelopmentBundle\Util\Tests\RequestCookiesTrait;
use KupShop\KupShopBundle\Config;
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Context\UserContext;
use KupShop\MarketingBundle\EventListener\OrderConversionListener;
use KupShop\OrderingBundle\Util\CartFactory;
use KupShop\OrderingBundle\Util\Order\OrderInfo;
use KupShop\OrderingBundle\Util\Purchase\PurchaseUtil;
class CartTest extends DatabaseTestCase
{
use CartTestTrait;
use RequestCookiesTrait;
protected function tearDown(): void
{
parent::tearDown();
Delivery::clearCache();
}
public function testSharedAndNonSharedCart(): void
{
$cartFactory = $this->get(CartFactory::class);
$sharedCartFromPurchaseUtil = $this->get(PurchaseUtil::class)->getCart();
$sharedCartFromDI = $this->get(\KupShop\OrderingBundle\Cart::class);
$this->assertSame(spl_object_id($sharedCartFromDI), spl_object_id($sharedCartFromPurchaseUtil), 'Rikam si o shared Cart, takze musi byt vzdy stejny ID objektu v pameti');
$nonSharedCartFromFactory = $cartFactory->create();
$this->assertNotSame(spl_object_id($sharedCartFromDI), spl_object_id($nonSharedCartFromFactory), 'Shared a non-shared cart nesmi byt stejny');
$this->assertNotSame(spl_object_id($nonSharedCartFromFactory), spl_object_id($cartFactory->create()), 'Mam non-shared cart a vytvarim dalsi non-shared cart, ktery nesmi byt stejny jako ten predesly');
}
public function testNonSharedCartDependencies(): void
{
$cart = $this->get(CartFactory::class)->create();
$requiredProperties = $this->getRequiredProperties($cart);
$reflection = new ReflectionClass($cart);
// test that all required properties are not null
foreach ($reflection->getProperties() as $property) {
if (!in_array($property->getName(), $requiredProperties)) {
continue;
}
$property->setAccessible(true);
$this->assertNotNull($property->getValue($cart), '#[Required] property nemuze byt null pokud se vytvari non-shared kosik pres CartFactory!');
}
}
// otestuje, ze se objednavka vytvori po novu pres PurchaseState
/** @dataProvider data_purchaseStateProvider */
public function testOrderSubmitFromPurchaseState($applyModule): void
{
$applyModule();
$this->addModule(Modules::ORDERS, Modules::SUB_ORDERS_FROM_PURCHASE_STATE);
$this->prepareCart();
$this->insertProduct(1, 16, 3);
$this->insertProduct(10);
$order = $this->submitOrder();
$this->removeModule(Modules::ORDERS, Modules::SUB_ORDERS_FROM_PURCHASE_STATE);
$this->assertInstanceOf(Order::class, $order);
$this->assertCount(2, $order->items);
$this->assertEquals(4009, $order->getTotalPrice()->getPriceWithVat()->asFloat());
$this->assertEqualsWithDelta($this->cart->totalPricePay->asFloat(), $this->order->total_price->asFloat(), 0.01);
$this->assertEquals(OrderInfo::ORDER_SOURCE_SHOP, $order->source);
}
/** @dataProvider data_DeliveryPriceNotOnFirstStep */
public function testCartDeliveryPriceNotOnFirstStep($goBack, $expectedPrice)
{
$this->createCart();
$this->insertProduct(1, 16, 1);
$this->setDeliveryType(2);
$this->visitStep('delivery');
if ($goBack) {
$this->cart->actualStep = 'cart';
}
$this->cart->createFromDB();
$this->assertEquals($expectedPrice, $this->cart->totalPricePay->asFloat());
}
public function data_DeliveryPriceNotOnFirstStep()
{
yield [true, 800];
yield [false, 870];
}
/** @dataProvider data_purchaseStateProvider */
public function testOrderingRegistrationInForeignCurrency($applyModule)
{
$applyModule();
$order = $this->getContextManager()->activateContexts(
[
CurrencyContext::class => 'EUR',
UserContext::class => ContextManager::FORCE_EMPTY,
],
function () {
$this->createCart();
$this->insertProduct(1, 16, 1);
$this->setInvoice();
$this->setDeliveryType();
$this->cart->register = true;
$this->cart->createFromDB();
return $this->cart->submitOrder();
}
);
$this->assertEquals('EUR', $order->currency);
}
/**
* @dataProvider data_orderingRegistration
*/
public function testOrderingRegistration($newsletterEnable, $getNewsExpect)
{
$settings = Settings::getDefault();
$settings->newsletter['enable'] = $newsletterEnable;
$this->createCart();
$this->insertProduct(1, 16, 1);
$this->setInvoice();
$this->setDeliveryType();
$this->cart->register = true;
$this->cart->createFromDB();
$order = $this->cart->submitOrder();
// createFromLogin to avoid cached user when using getCurrentUser
$user = User::createFromLogin('test@wpj.cz');
$this->assertInstanceOf(Order::class, $order);
$this->assertEquals('800', $order->total_price->asFloat());
$this->assertEquals($user['email'], 'test@wpj.cz');
$this->assertEquals($user['get_news'], $getNewsExpect);
}
public function data_orderingRegistration()
{
return [
['Y', 'N'],
['N', 'Y'],
];
}
/** @dataProvider data_purchaseStateProvider */
public function testGetPayments($applyModule)
{
$applyModule();
$this->createCart();
$this->cart->createFromDB();
$payments = $this->cart->getPayments();
$this->assertEquals(12, $payments[1]['price']['value_with_vat']->asFloat());
$this->assertEquals(round(12 / 1.21, 4), $payments[1]['price']['value_without_vat']->asFloat());
$this->assertEquals(24, $payments[2]['price']['value_with_vat']->asFloat());
$this->assertEquals(36, $payments[3]['price']['value_with_vat']->asFloat());
$this->assertEquals(48, $payments[4]['price']['value_with_vat']->asFloat());
}
/** @dataProvider data_purchaseStateProvider */
public function testAddItemToCart($applyModule)
{
$applyModule();
$this->loginUser(1);
$this->createCart();
$this->insertProduct(1, 16);
$this->cart->createFromDB();
$this->assertEquals(800, $this->cart->totalPriceWithVat->asFloat());
$this->checkOrderPriceIsSameAsCart();
}
/** @dataProvider data_purchaseStateProvider */
public function testAddItemToCartNegativePieces($applyModule)
{
$applyModule();
$this->createCart();
$item = ['id_product' => 1, 'id_variation' => 16, 'pieces' => -1];
$itemId = $this->cart->addItem($item);
$this->assertEmpty($itemId);
$item = ['id_product' => 1, 'id_variation' => 16, 'pieces' => 0];
$itemId = $this->cart->addItem($item);
$this->assertEmpty($itemId);
$this->cart->createFromDB();
$this->assertEquals(0, $this->cart->totalPriceWithVat->asFloat());
$this->assertEmpty($this->cart->products);
}
/** @dataProvider data_purchaseStateProvider */
public function testCheckItemsInCartNotInStore($applyModule)
{
$applyModule();
// order_not_in_store == Y
$this->createCart();
$this->insertProduct(1, 16, 2);
$this->cart->createFromDB();
$return = $this->cart->checkCartItems();
$this->assertEquals(null, $return);
}
/** @dataProvider data_purchaseStateProvider */
public function testCheckItemsInCartInStore($applyModule)
{
$applyModule();
global $dbcfg, $cfg;
$cfg['Modules']['products_suppliers'] = false;
$dbcfg->order_not_in_store = 'N';
// order_not_in_store == N
$this->createCart();
$this->insertProduct(1, 16, 2);
$this->cart->createFromDB();
$this->expectException(\KupShop\OrderingBundle\Exception\CartValidationException::class);
$return = $this->cart->checkCartItems();
$this->assertEquals(30, $return);
}
public function testCheckItemsInCartVisibility()
{
$this->createCart();
$this->insertProduct(4, 1, 1);
$this->cart->createFromDB();
// cart product variation is visible
$return = $this->cart->checkCartItems();
$this->assertEquals(null, $return);
$qb = sqlQueryBuilder()->update('products_variations')
->directValues(['figure' => 'N'])
->andWhere('id=1')->execute();
// cart product variation is not visible
$return = $this->cart->checkCartItems();
$this->assertEquals(31, $return);
}
/** @dataProvider data_purchaseStateProvider */
public function testCheckItemsInCartInSupplierStore($applyModule)
{
$applyModule();
global $dbcfg, $cfg;
$cfg['Modules']['products_suppliers'] = ['delivery_time' => -2];
$dbcfg->order_not_in_store = 'N';
// order_not_in_store == N
$this->createCart();
$this->insertProduct(1, 16, 2);
$this->cart->createFromDB();
$return = $this->cart->checkCartItems();
$this->assertEquals(null, $return);
}
public function getDataSet()
{
return $this->getJsonDataSet(
/* @lang JSON */ '
{"products_of_suppliers" : [
{
"id":1,
"id_product":1,
"id_variation":16,
"id_supplier":1,
"code":123,
"in_store":2
}
]}'
);
}
/** @dataProvider data_purchaseStateProvider */
public function testAddItemToCartInEuro($applyModule)
{
$applyModule();
$this->loginUser(1);
$c = $this->get(\KupShop\KupShopBundle\Context\CurrencyContext::class);
$c->activate('EUR');
$currency = $this->get(\KupShop\KupShopBundle\Context\CurrencyContext::class)->getActive();
$currency->setRate(toDecimal(26));
$currency->setPriceRoundOrder('0');
$currency->setPriceRound('0');
$this->createCart();
$this->insertProduct(1, 16);
$this->cart->createFromDB();
$this->assertEquals(800 / 26, $this->cart->totalPricePay->asFloat(), '', 0.01);
$this->checkOrderPriceIsSameAsCart();
changeCurrency();
}
/** @dataProvider data_purchaseStateProvider */
public function testAddItemToCartInEuroWithRounding($applyModule)
{
$applyModule();
$this->loginUser(1);
$context = $this->get(\KupShop\KupShopBundle\Context\CurrencyContext::class);
$context->activate('EUR');
$currency = $context->getActive();
$currency->setRate(26);
$currency->setPriceRoundOrder('100');
$this->createCart();
$this->insertProduct(1, 16);
$this->cart->createFromDB();
$this->assertEquals(round(800 / 26), $this->cart->totalPricePay->asFloat(), '', 0.01);
$this->checkOrderPriceIsSameAsCart();
}
public function testSendZboziConversion()
{
// Prepare settings
Settings::getDefault()->analytics = [
'zbozi_cz_feedback' => [
'ID' => '129931',
'secret_key' => 'CXIGnEMhnOrP32au62B7k5tgAOhiTiyK',
],
];
// Restart container to force reload event listeners
$this->tearDownContainer();
$this->restoreDefaultCtrl();
$zboziClientMock = $this->getMockBuilder(\Soukicz\Zbozicz\Client::class)
->setMethods(['sendOrder'])
->setConstructorArgs(['129931', 'CXIGnEMhnOrP32au62B7k5tgAOhiTiyK'])
->getMock();
$data = [];
$zboziClientMock->expects($this->once())->method('sendOrder')->with(
$this->callback(function (Soukicz\Zbozicz\Order $order) use (&$data, $zboziClientMock) {
$data = json_decode_strict($zboziClientMock->createRequest($order)->getBody(), true);
return true;
})
);
$requestStack = $this->getRequestStackWithCookies('cookie-bar', 'analytics_storage');
$listenerMock = $this->getMockBuilder(OrderConversionListener::class)
->setMethods(['getZboziClient'])
->setConstructorArgs(
[
$this->get(\KupShop\KupShopBundle\Util\Price\PriceUtil::class),
$requestStack,
$this->get(\KupShop\KupShopBundle\Context\CountryContext::class),
$this->get(\KupShop\KupShopBundle\Context\CurrencyContext::class),
]
)
->getMock();
$listenerMock->method('getZboziClient')->willReturn($zboziClientMock);
$listenerMock->setDomainContext(\KupShop\KupShopBundle\Util\Contexts::get(\KupShop\KupShopBundle\Context\DomainContext::class));
$this->set(OrderConversionListener::class, $listenerMock);
$this->loginUser(2);
$context = $this->get(\KupShop\KupShopBundle\Context\CurrencyContext::class);
$context->activate('EUR');
$this->createCart();
$this->insertProduct(1, 16);
$this->cart->createFromDB();
$order = $this->cart->submitOrder();
$this->assertInstanceOf('\Order', $order);
$this->assertNotEmpty($data);
$this->assertEquals([
'PRIVATE_KEY' => 'CXIGnEMhnOrP32au62B7k5tgAOhiTiyK',
'orderId' => $order->order_no,
'email' => 'wpj@wpj.cz',
'deliveryType' => 'GLS',
'deliveryPrice' => 104,
'paymentType' => 'dobírka PPL',
'cart' => [
[
'productName' => 'DeWALT DeWALT DCD780C2 aku vrtačka',
'itemId' => '9',
'unitPrice' => 6000,
'quantity' => '1',
],
[
'productName' => 'Nike NIKE Capri LACE Test Dlouheho Nazvu Produktu Test Dlouheho Produktu Tes (Velikost: 45)',
'itemId' => '1_16',
'unitPrice' => 800,
'quantity' => '1',
],
],
'sandbox' => false,
'otherCosts' => 0,
], $data);
}
/** @dataProvider data_purchaseStateProvider */
public function testHeurekaConversionOptions($applyModule)
{
$applyModule();
/** @var OrderConversionListener $listener */
$listener = $this->get(OrderConversionListener::class);
/** @var \KupShop\KupShopBundle\Context\CountryContext $countryContext */
$countryContext = $this->get(\KupShop\KupShopBundle\Context\CountryContext::class);
$languageContext = $this->get(\KupShop\KupShopBundle\Context\LanguageContext::class);
// Prepare settings
Settings::getDefault()->analytics = [
'heureka_overeno' => [
'ID' => 'dksag41s2fdsd10vs',
],
];
$this->assertEquals(
['heureka_id' => 'dksag41s2fdsd10vs', 'options' => ['service' => ShopCertification::HEUREKA_CZ]],
$listener->getHeurekaOptions()
);
$languageContext->activate('sk');
Settings::getDefault()->analytics = [
'heureka_overeno' => [
'ID' => 'dksag41s2fdsd10vs',
],
];
$this->assertEquals(
['heureka_id' => 'dksag41s2fdsd10vs', 'options' => ['service' => ShopCertification::HEUREKA_SK]],
$listener->getHeurekaOptions()
);
$cfg = Config::get();
$languageContext->activate('cs');
$cfg['Modules']['translations'] = false;
\Settings::clearCache(true);
Settings::getDefault()->analytics = [
'heureka_overeno' => [
'ID' => 'dksag41s2fdsd10vs',
],
];
$this->assertEquals(
['heureka_id' => 'dksag41s2fdsd10vs', 'options' => ['service' => ShopCertification::HEUREKA_CZ]],
$listener->getHeurekaOptions()
);
Settings::getDefault()->analytics = [
'heureka_overeno' => [
'ID' => 'dksag41s2fdsd10vs',
'ID_SK' => 'SKdksag41s2fdsd10vsSK',
],
];
$languageContext->activate('sk');
$countryContext->activate('SK');
Settings::getDefault()->analytics = [
'heureka_overeno' => [
'ID' => 'dksag41s2fdsd10vs',
'ID_SK' => 'SKdksag41s2fdsd10vsSK',
],
];
$this->assertEquals(
['heureka_id' => 'SKdksag41s2fdsd10vsSK', 'options' => ['service' => ShopCertification::HEUREKA_SK]],
$listener->getHeurekaOptions()
);
}
/** @dataProvider data_purchaseStateProvider */
public function testFreeDelivery($applyModule)
{
$applyModule();
sqlQuery('UPDATE delivery_type SET price_dont_countin_from=800 WHERE id=4');
$this->createCart();
$this->setInvoice();
$this->insertProduct(1, 16);
$this->setDeliveryType(4);
$this->checkOrderPriceIsSameAsCart();
$this->assertEquals('800', $this->cart->totalPricePay->asFloat());
}
/** @dataProvider data_purchaseStateProvider */
public function testFreeDeliveryForUnregisteredWithUser($applyModule)
{
$applyModule();
// pro neregistrované je nastaveno 800, ale melo by platit i pro registrovane.
sqlQuery('UPDATE delivery_type SET price_dont_countin_from=800 WHERE id=4');
$user = User::createFromId(1);
$user->activateUser();
$this->createCart();
$this->insertProduct(1, 16);
$this->setDeliveryType(4);
$this->checkOrderPriceIsSameAsCart();
$this->assertEquals('800', $this->cart->totalPricePay->asFloat());
}
public function testFreeDeliveryForRegisteredWithoutUser()
{
// Pro neregistrované není nic nastaveno, pro registrované od 400, tzn tento neni registrovany a ma se mu pricist doprava
sqlQuery('UPDATE delivery_type SET price_dont_countin_from_reg=400 WHERE id=4');
$this->createCart();
$this->setInvoice();
$this->insertProduct(1, 16);
$this->setDeliveryType(4);
$this->visitStep('delivery');
$this->checkOrderPriceIsSameAsCart();
$this->assertEquals('904', $this->cart->totalPricePay->asFloat());
}
/** @dataProvider data_purchaseStateProvider */
public function testFreeDeliveryForRegisteredWithtUser($applyModule)
{
$applyModule();
// Pro neregistrované není nic nastaveno, pro registrované od 400, tzn tento neni registrovany a nema se mu pricist doprava
sqlQuery('UPDATE delivery_type SET price_dont_countin_from_reg=400 WHERE id=4');
$user = User::createFromId(1);
$user->activateUser();
$this->createCart();
$this->insertProduct(1, 16);
$this->setDeliveryType(4);
$this->visitStep('delivery');
$this->checkOrderPriceIsSameAsCart();
$this->assertEquals('800', $this->cart->totalPricePay->asFloat());
}
/** @dataProvider data_purchaseStateProvider */
public function testCartClean($applyModule)
{
$applyModule();
// vytvoříme nový košík, který by neměl být smazán - ostatní jsou staršího data, tak dojde k jejich smazání
$this->createCart();
$this->insertProduct(1, 16);
$cl = new \KupShop\OrderingBundle\EventListener\CronListener();
$cl->cartCleanup();
$this->assertTableRowCount('cart', 2);
}
/** @dataProvider data_purchaseStateProvider */
public function testDeliveryPrice(callable $applyModule): void
{
$applyModule();
$cart = $this->prepareCart();
$cart->setTransport(3);
$product = [
'id_product' => 7,
'id_variation' => 8,
'pieces' => 1,
];
$cart->addItem($product);
$cart->createFromDB();
$order = $cart->submitOrder();
$price = $order->getTotalPrice();
$this->assertEqualsWithDelta(922.0, $price->getPriceWithVat()->asFloat(), 1);
}
}