Files
kupshop/bundles/KupShop/WatchdogBundle/Tests/WatchdogTest.php
2025-08-02 16:30:27 +02:00

406 lines
13 KiB
PHP

<?php
namespace KupShop\WatchdogBundle\Tests;
use KupShop\CatalogBundle\ProductList\ProductCollection;
use KupShop\DevelopmentBundle\MailArchive;
use KupShop\DevelopmentBundle\Util\Tests\RequestSessionTrait;
use KupShop\WatchdogBundle\Util\Watchdog;
use Query\Operator;
class WatchdogTest extends \DatabaseTestCase
{
use RequestSessionTrait;
protected $backupGlobalsBlacklist = ['dbCon', 'cfg'];
/** @var Watchdog */
public $watchdog;
/**
* @var WatchdogMock
*/
public $watchdogMock;
/**
* @var MailArchive
*/
public $mailArchive;
public function setUp(): void
{
parent::setUp();
$this->prepareRequestStackSession();
$this->watchdog = $this->get(\KupShop\WatchdogBundle\Util\Watchdog::class);
$this->watchdogMock = new WatchdogMock(
$this->get(\Symfony\Component\HttpFoundation\RequestStack::class),
$this->get(\KupShop\KupShopBundle\Context\ContextManager::class),
$this->get(\KupShop\KupShopBundle\Email\WatchdogEmail::class)
);
$this->mailArchive = $this->get(MailArchive::class);
$this->mailArchive->clearArchive();
}
public function testGenerateUserWatchdogDoesNotSendMailOnEmptyUserWatches()
{
$this->watchdog->generateUserWatchdog(4);
$this->assertEmpty($this->mailArchive->getArchive());
}
public function testGenerateUserWatchdogSendsNotification()
{
$this->watchdog->generateUserWatchdog(1);
$mailArchive = $this->get(MailArchive::class);
$mails = $mailArchive->getArchive();
$this->assertTrue(count($mails) > 0);
$message = $mailArchive->getLast();
$this->assertContains('Hlídané zboží můžete nyní objednat', $message['subject']);
// assert users watchdog was deleted
$userWatchdog = sqlQueryBuilder()
->select('*')->from('products_watchdog')
->where(Operator::equals(['id_user' => 1]))
->execute()->fetchAll();
$this->assertEmpty($userWatchdog);
}
public function testDoNotSendWatchdogToBlockedUser()
{
$this->watchdog->generateUserWatchdog(5);
$mailArchive = $this->get(MailArchive::class);
$message = $mailArchive->getLast();
$this->assertEmpty($message);
}
public function testSendWatchdogToNotRegisteredUser()
{
$this->watchdog->generateUserWatchdog(6);
$mailArchive = $this->get(MailArchive::class);
$message = $mailArchive->getLast();
$this->assertNotEmpty($message);
$this->assertEquals('newsletter@wpj.cz', $message['to']);
}
/**
* @dataProvider dataSet_testGenerateUserWatchdogSendsCorrectProducts
*/
public function testGenerateUserWatchdogSendsCorrectProducts(int $userId, array $expectedProductIds)
{
$sendUserNotificationCalled = false;
$this->watchdogMock->mock(
'sendUserNotification',
function (\User $user, ProductCollection $products) use (
&$sendUserNotificationCalled,
$expectedProductIds
) {
$this->assertCount(count($expectedProductIds), $products);
$this->assertSame($expectedProductIds, $products->getKeys());
$sendUserNotificationCalled = true;
}
);
$this->watchdogMock->generateUserWatchdog($userId);
$this->assertTrue($sendUserNotificationCalled);
}
public function dataSet_testGenerateUserWatchdogSendsCorrectProducts(): array
{
return [
// Hlidam cely produkt a 3 varianty byly naskladneny
[1, ['2/9', '2/10', '2/12']],
// Hlidam pouze konkretni varianty a jedna varianta byla naskladnena
[3, ['4/1']],
];
}
/**
* @dataProvider dataSet_testUpdateInStore
*/
public function testUpdateInStore($userId, $expectedResult)
{
$this->watchdog->updateLastInStore($userId);
$result = sqlQueryBuilder()
->select('last_in_store')
->from('products_watchdog')
->execute()->fetchAllAssociative();
$this->assertSame($expectedResult, array_column($result, 'last_in_store'));
}
public function dataSet_testUpdateInStore(): array
{
return [
[null, [9, 9, 5, 0, 9, 9, 5, 5, 0, 0]],
[1, [9, null, null, null, null, null, null, null, null, null]],
[2, [null, 9, null, null, null, null, null, null, null, null]],
[3, [null, null, 5, 0, null, null, null, null, null, null]],
];
}
public function testGenerateWatchdogsCallsGenerateUserWatchdogForEveryMatchedUser()
{
$counter = 0;
$this->watchdogMock->mock('generateUserWatchdog', function () use (&$counter) {
++$counter;
});
$this->watchdogMock->generateWatchdogs();
$this->assertSame(7, $counter);
}
public function testAddProductWatchdog()
{
$this->watchdog->addWatchdog(1, 3);
$this->assertCount(1, sqlQuery('SELECT * FROM products_watchdog WHERE id_user=1 AND id_product=3')->fetchAll());
}
public function testDropProductWatchdog()
{
$this->assertCount(1, sqlQuery('SELECT * FROM products_watchdog WHERE id_user = 2 AND id_product = 2')->fetchAll());
$this->watchdog->dropWatchdog(2, 2);
$this->assertEmpty(sqlQuery('SELECT * FROM products_watchdog WHERE id_user = 2 AND id_product = 2')->fetchAll());
}
public function testDropVariationWatchdog()
{
$this->assertCount(2, sqlQuery('SELECT * FROM products_watchdog WHERE id_user = 3 AND id_product = 4')->fetchAll());
$this->watchdog->dropWatchdog(3, 4, 1);
$this->assertCount(1, sqlQuery('SELECT * FROM products_watchdog WHERE id_user = 3 AND id_product = 4')->fetchAll());
}
/** @dataProvider data_testDropProductWatchdogPartial */
public function testDropProductWatchdogPartial(array $watchdogInfo, array $expectedBefore, ?array $expectedAfter, array $dropParts): void
{
[$userId, $productId, $variationId] = $watchdogInfo;
[$availability, $price] = $dropParts;
$watchdog = $this->watchdog->getWatchdog($userId, $productId, $variationId);
// stav pred dropnutim
$this->assertEquals($expectedBefore, [$watchdog['availability'], $watchdog['price']]);
// zavolat drop
$this->watchdog->dropWatchdog($userId, $productId, $variationId, $availability, $price);
$watchdog = $this->watchdog->getWatchdog($userId, $productId, $variationId);
// stav po dropnuti
if ($expectedAfter === null) {
$this->assertEmpty($watchdog);
} else {
$this->assertEquals($expectedAfter, [$watchdog['availability'], $watchdog['price']]);
}
}
public function data_testDropProductWatchdogPartial(): array
{
return [
// chci smazat pouze watchdog pro dostupnost a cenu zachovat
[[8, 4, 1], [1, 1000], [0, 1000], [true, false]],
// chci smazat pouze cenu a dostupnost zachovat
[[8, 4, 1], [1, 1000], [1, null], [false, true]],
// hlidani dostupnosti je vypnute a chci vypnout hlidani ceny - mel by se smazat cely watchdog
[[9, 1, 16], [0, 100], null, [false, true]],
// hlidani dostupnosti je vypnute a chci vypnout hlidani ceny a chybi nastavena varianta - mel by se smazat cely watchdog
[[9, 1, null], [0, 100], null, [false, true]],
// smazat jak hlidani ceny, tak hlidani dostupnosti
[[8, 4, 1], [1, 1000], null, [true, true]],
];
}
public function testAddPriceWatchdog(): void
{
$this->watchdog->addWatchdog(1, 3, null, false, 100);
$watchdogPrice = $this->watchdog->getWatchdog(1, 3)['price'];
$this->assertEquals(100, $watchdogPrice);
}
public function testAddPriceWatchdogUpdated(): void
{
// pridam watchdog na cenu
$this->watchdog->addWatchdog(1, 3, null, false, 100);
$watchdog = $this->watchdog->getWatchdog(1, 3);
$this->assertEquals([0, 100], [$watchdog['availability'], $watchdog['price']], 'Zkontrolovat, ze se zapnulo hlidani ceny, ale nezapnulo se hlidani skladu');
// pridat watchdog znovu - tentokrat na sklad
$this->watchdog->addWatchdog(1, 3);
$watchdog = $this->watchdog->getWatchdog(1, 3);
$this->assertEquals([1, 100], [$watchdog['availability'], $watchdog['price']], 'Zkontrolovat, ze se zapnulo hlidani skladu');
}
public function testPriceWatchdogNotificationIsSent(): void
{
$this->watchdog->generateUserWatchdog(7);
$message = $this->mailArchive->getLast();
$this->assertNotEmpty(
$message,
'E-mail s notifikaci byl odeslan'
);
$watchdog = sqlQueryBuilder()
->select('*')
->from('products_watchdog')
->where(Operator::equals(['id_user' => 7]))
->execute()->fetchAssociative();
$this->assertFalse($watchdog, 'Zkontrolovat, ze watchdog byl uspesne smazan');
}
public function testPriceWatchdogWithInStoreWatchdogNotificationIsSent(): void
{
$this->watchdog->generateUserWatchdog(8);
$this->watchdog->updateLastInStore(8);
$this->assertNotEmpty(
$this->mailArchive->getLast(),
'Otestovat, ze e-mail s notifikaci byl odeslan'
);
$watchdog = sqlQueryBuilder()
->select('*')
->from('products_watchdog')
->where(Operator::equals(['id_user' => 8]))
->execute()->fetchAssociative();
$this->assertEquals(
// odeslal se watchdog na dostupnost, ale na cenu furt zustal
[1000, 5],
[$watchdog['price'], $watchdog['last_in_store']],
'Zkontrolovat, ze watchdog nebyl smazan, protoze byl odeslan watchdog na cenu, ale na sklad musi furt zustat'
);
}
public function testPriceWatchdogIsNotSent(): void
{
$this->watchdog->generateUserWatchdog(9);
$this->assertEmpty(
$this->mailArchive->getLast(),
'Otestovat, ze e-mail s notifikaci nebyl odeslan'
);
}
public function testDontRemoveUserWhenDontHaveEnoughtItems()
{
// Add users to watchdog
$this->watchdog->addWatchdog(1, 3);
$this->watchdog->addWatchdog(2, 3);
$this->watchdog->addWatchdog(3, 3);
$this->watchdog->addWatchdog(4, 3);
$userWatchdog = sqlQueryBuilder()
->select('count(id_user) as id_user')->from('products_watchdog')
->where(Operator::equals(['id_product' => 3]))
->execute()->fetchAll();
$this->assertEquals('4', $userWatchdog[0]['id_user']);
// Need one item in_store on product_id 3
sqlQuery('UPDATE products SET in_store = 1 WHERE id = 3');
$count = sqlQuery('SELECT in_store FROM products WHERE id = 3')->fetchAll();
$this->assertEquals('1', $count['0']['in_store']);
// Ask if have enought products
$this->watchdog->generateUserWatchdog(1);
$userWatchdog = sqlQueryBuilder()
->select('count(id_user) as id_user')->from('products_watchdog')
->where(Operator::equals(['id_product' => 3]))
->execute()->fetchAll();
$this->assertEquals('4', $userWatchdog[0]['id_user']);
}
public function testDropWatchdogThrows()
{
$this->expectException(\TypeError::class);
$this->watchdog->dropWatchdog(null);
}
public function testAddVariationWatchdog()
{
$this->watchdog->addWatchdog(1, 4, 1);
$this->assertCount(1, sqlQuery(
'SELECT * FROM products_watchdog WHERE id_user=1 AND id_product=4 AND id_variation=1'
)->fetchAll());
}
public function testIsWatchdogThrowsOnInvalidArgument()
{
$this->expectException(\TypeError::class);
$this->watchdog->isWatchdog(1, null);
}
/**
* @dataProvider dataSet_testIsWatchdog
*/
public function testIsWatchdog($expected, array $args)
{
$this->assertSame($expected, call_user_func_array([$this->watchdog, 'isWatchdog'], $args));
}
public function dataSet_testIsWatchdog(): array
{
return [
[true, [1, 2]],
[true, [3, 4, 1]],
[false, [3, 4]],
[false, [1, 1]],
[false, [1, 1, 1]],
];
}
public function sendMailMock($from, $for, $subject, $message, $contentType)
{
$this->emailSent = true;
SendMail($from, $for, $subject, $message, $contentType);
}
public function getDataSet()
{
return $this->getJsonDataSetFromFile();
}
}
class WatchdogMock extends Watchdog
{
use \MockingTrait;
public function updateLastInStore($id_user = null)
{
return $this->call(__FUNCTION__, func_get_args());
}
public function generateUserWatchdog($id_user, bool $contextsByUser = true)
{
return $this->call(__FUNCTION__, func_get_args());
}
public function sendUserNotification($user, $products)
{
return $this->call(__FUNCTION__, func_get_args());
}
}