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

201 lines
8.1 KiB
PHP

<?php
namespace KupShop\LabelsBundle\Tests;
use KupShop\CatalogBundle\ProductList\ProductList;
use KupShop\LabelsBundle\Util\LabelFilterSpecs;
use KupShop\LabelsBundle\Util\ProductLabelUtil;
use Query\Operator;
class LabelsTest extends \DatabaseTestCase
{
private ProductLabelUtil $productLabelUtil;
private LabelFilterSpecs $labelFilterSpecs;
private ProductList $productList;
protected function setUp(): void
{
parent::setUp();
$this->productLabelUtil = $this->get(ProductLabelUtil::class);
$this->labelFilterSpecs = $this->get(LabelFilterSpecs::class);
$this->productList = $this->get(ProductList::class);
}
protected function getDataSet()
{
return $this->getJsonDataSetFromFile();
}
/** @dataProvider data_testProductLabelsMultiFetch */
public function testProductLabelsMultiFetch(?string $visibility, int $expectedLabelsCount, int $expectedVisibleLabelsCount, bool $loggedUser = false): void
{
if ($loggedUser) {
$user = \User::createFromId(1);
$user->activateUser();
}
$products = $this->productList->andSpec(Operator::equals(['p.id' => 9411]))
->getProducts();
$products->fetchProductLabels($visibility);
$product = $products->first();
$this->assertCount($expectedLabelsCount, $product->labels);
$this->assertCount($expectedVisibleLabelsCount, array_filter($product->labels, fn ($x) => $x['is_visible']));
}
public function data_testProductLabelsMultiFetch(): iterable
{
yield 'Vsechny aktivni stitky by mely byt nactene u produktu a vsechny i jako viditelne' => [null, 2, 2];
yield 'Vsechny stitky by mely byt nactene u produktu a vsechny i jako viditelne ' => ['all', 4, 4];
yield 'Detail produktu - celkove dva aktivni stitky, a oba se maji zobrazovat na detailu' => ['detail', 2, 2];
yield 'Seznam produktu - celkove dva aktivni stitky, ale jen jeden se ma zobrazovat na seznamu' => ['list', 2, 1];
yield 'Seznam - celkove dva aktivni stitky, ale jen jeden se ma zobrazovat na seznamu a uzivatel prihlaseny' => ['list', 3, 2, true];
}
public function testAutomaticLabelAssignment()
{
$filterSpecs = $this->labelFilterSpecs->getSpecs(['active' => true, 'id' => 1]);
$productLabelRelation = sqlQueryBuilder()
->select('*')
->from('product_labels_relation', 'plr')
->where(Operator::equals(['id_label' => 1]))
->execute()
->fetchAllAssociative();
$manualAssignedItem = $this->getProductByProperty($productLabelRelation, 9410);
$this->assertCount(1, $productLabelRelation);
$this->assertNotNull($manualAssignedItem);
$this->assertEquals(0, $manualAssignedItem['generated']);
$labels = sqlQueryBuilder()
->select('l.id, l.data')
->from('labels', 'l')
->andWhere($filterSpecs)
->execute()
->fetchAssociative();
$labelData = json_decode($labels['data'], true);
// Auto assigned products by filter
$this->productLabelUtil->updateProductLabelRelationsByAutoAssignment(1, $labelData);
$productLabelRelation = sqlQueryBuilder()
->select('*')
->from('product_labels_relation', 'plr')
->where(Operator::equals(['id_label' => 1]))
->execute()
->fetchAllAssociative();
$this->assertCount(3, $productLabelRelation);
$this->assertEquals($manualAssignedItem, $this->getProductByProperty($productLabelRelation, 9410));
$this->assertEquals(1, $this->getProductByProperty($productLabelRelation, 42916)['generated']);
// Set filter to nonsense data (to delete generated)
$labelData['product_filter']['in_store_range']['max'] = '9000000';
$labelData['product_filter']['in_store_range']['min'] = '8999999';
// Auto delete assigned products
$this->productLabelUtil->updateProductLabelRelationsByAutoAssignment(1, $labelData);
$productLabelRelation = sqlQueryBuilder()
->select('*')
->from('product_labels_relation', 'plr')
->where(Operator::equals(['id_label' => 1]))
->execute()
->fetchAllAssociative();
$this->assertCount(1, $productLabelRelation);
$this->assertEquals($manualAssignedItem, $this->getProductByProperty($productLabelRelation, 9410));
}
/** @dataProvider data_testAutomaticLabelAssignmentActivationTypes */
public function testAutomaticLabelAssignmentActivationTypes(int $labelId, array $labelData, ?callable $prepareDataFn, int $expectedAssigmentCount): void
{
$this->assertEquals(0, $this->getLabelAssigmentCount($labelId));
$filterSpecs = $this->labelFilterSpecs->getSpecs(['active' => true, 'id' => $labelId]);
$label = sqlQueryBuilder()
->select('l.id, l.data')
->from('labels', 'l')
->andWhere($filterSpecs)
->execute()->fetchAssociative();
$data = json_decode($label['data'] ?: '', true) ?: [];
$data = array_merge($data, $labelData);
if ($prepareDataFn) {
$prepareDataFn();
}
$this->productLabelUtil->updateProductLabelRelationsByAutoAssignment($labelId, $data);
$this->assertEquals($expectedAssigmentCount, $this->getLabelAssigmentCount($labelId));
}
private function getProductByProperty($array, $id): array
{
return array_reduce($array, static function ($carry, $item) use ($id) {
return $item['id_product'] === $id ? $item : $carry;
}, []);
}
private function getLabelAssigmentCount(int $labelId): int
{
$result = sqlQueryBuilder()
->select('COUNT(*)')
->from('product_labels_relation', 'plr')
->where(Operator::equals(['plr.id_label' => $labelId]))
->execute()->fetchOne();
return $result ?: 0;
}
private function data_testAutomaticLabelAssignmentActivationTypes(): array
{
$activeIntervalFrom = (new \DateTime())->sub(new \DateInterval('P4D'))->format('d.m.Y H:i:s');
$activeIntervalTo = (new \DateTime())->add(new \DateInterval('P4D'))->format('d.m.Y H:i:s');
// labelId, labelData, prepareDataFn, expectedAssigmentCount
return [
// typ "na akci" - aktivuje se na produkty, na ktere plati podminka "14 dni od zalozeni produktu"
[2, ['active_type' => 'Y', 'active_action_days' => 14, 'active_action_type' => 'from_product_creation'], fn () => $this->prepareData_testAutomaticLabelAssignmentActivationTypes_0(), 1],
// typ "na akci" - nic by se nemelo zaradit, protoze nemam zadny produkt, na ktery by platila podminka
[2, ['active_type' => 'Y', 'active_action_days' => 14, 'active_action_type' => 'from_product_creation'], fn () => $this->prepareData_testAutomaticLabelAssignmentActivationTypes_1(), 0],
// typ "infinite" - melo by se zaradit vsechno zbozi, protoze nemam zadny filtr
[2, ['active_type' => 'N'], null, 10],
];
}
private function prepareData_testAutomaticLabelAssignmentActivationTypes_0(): void
{
// vsem produktum nastavim aktualni datum
sqlQueryBuilder()
->update('products')
->directValues(['date_added' => (new \DateTime('2022-10-01'))->format('Y-m-d H:i:s')])
->execute();
// jednomu produktu nastavim datum tak, aby byl starsi jak 14 dnu a tim padem se na nej aplikuje akce "14 dni od vytvoreni produktu"
sqlQueryBuilder()
->update('products')
->directValues(['date_added' => (new \DateTime())->format('Y-m-d H:i:s')])
->where(Operator::equals(['id' => 16]))
->execute();
}
private function prepareData_testAutomaticLabelAssignmentActivationTypes_1(): void
{
// vsem produktum nastavim nejakej starej datum pridani
sqlQueryBuilder()
->update('products')
->directValues(['date_added' => (new \DateTime('2022-10-01'))->format('Y-m-d H:i:s')])
->execute();
}
}