bonusComputer = $this->autowire(BonusComputerMock::class); $this->bonusProvider = $this->get(BonusProvider::class); } public function testGetUsersWithoutOrdersInLast(): void { $result = $this->bonusComputer->getUsersWithoutOrdersInLastPub(4); // user 1 has an order today // user 2 does not have any recent orders and has active points // user 3 does not have active points $this->assertEquals(0, $this->bonusProvider->getActivePointsAmount(3)); $this->assertTrue($this->bonusProvider->getActivePointsAmount(2) > 0); $this->assertEquals([2, 4], $result, 'Špatně načtení uživatelé s bez nedávných objednávek!'); $result1 = $this->bonusComputer->getUsersWithoutOrdersInLastPub(40); $this->assertEquals([4], $result1, 'Špatně načtení uživatelé s bez nedávných objednávek!'); $result2 = $this->bonusComputer->getUsersWithoutOrdersInLastPub(60); $this->assertEmpty($result2, 'Špatně načtení uživatelé s bez nedávných objednávek!'); } public function testGetPointsThatWillExpire(): void { // user 1 has an order created 3 days ago $dateCreated = sqlQueryBuilder()->select('DATE(date_created)') ->from('orders') ->where('id_user = 1') ->execute()->fetchFirstColumn(); $this->assertEquals( (new \DateTimeImmutable())->sub(new \DateInterval('P3D'))->format('Y-m-d'), $dateCreated[0] ?? false, ); // user 1 has points that are 2 days old // remove time will be set to 60 // -> 60 - 2 = 58 // -> if the user would be notified today, the expiry_email_time would have to be set to 58 days // -> test lookup of today + 58 days (simulate remove_time = 60 & expiry_email_time = 58) $pointsCreatedDate = sqlQueryBuilder()->select('DATE(date_created)') ->from('bonus_points') ->where('id_user = 1') ->execute()->fetchFirstColumn(); $this->assertCount(1, $pointsCreatedDate); $this->assertEquals( (new \DateTimeImmutable())->sub(new \DateInterval('P2D'))->format('Y-m-d'), $pointsCreatedDate[0] ?? false, ); $result = $this->bonusComputer->getPointsThatExpireIn( 58, self::REMOVE_TIME, ); $this->assertEquals([ ['id_user' => 1, 'points' => 256], ], $result, 'Neočekávaní uživatelé, kterým by měly expirovat body z BonusProgramu!'); } public function testEmailGetsSent(): void { $this->set( BonusPointsExpiryEmail::class, $this->autowire(PointsExpiryEmailMock::class), ); $dbcfg = \Settings::getDefault(); $dbcfg->saveValue('bonus_program', [ 'expiry_email_time' => self::EXPIRY_EMAIL_TIME, 'remove_time' => self::REMOVE_TIME, ]); \Settings::clearCache(true); $listener = $this->get(CronListener::class); $listener->sendPointsExpiryEmails(); $this->assertCount( 1, PointsExpiryEmailMock::$payloads, 'E-mail o expiraci bodů nebyl odeslán!', ); // make points 1 day older sqlQueryBuilder()->update('bonus_points') ->where('id = 163') ->set('date_created', 'date_created - INTERVAL 1 DAY') ->execute(); PointsExpiryEmailMock::$payloads = []; $listener->sendPointsExpiryEmails(); $this->assertCount( 0, PointsExpiryEmailMock::$payloads, 'E-mail o expiraci bodů byl odeslán vícekrát!', ); // make points 1 day newer (1 + 1 from previous change) sqlQueryBuilder()->update('bonus_points') ->where('id = 163') ->set('date_created', 'date_created + INTERVAL 2 DAY') ->execute(); PointsExpiryEmailMock::$payloads = []; $listener->sendPointsExpiryEmails(); $this->assertCount( 0, PointsExpiryEmailMock::$payloads, 'E-mail o expiraci bodů byl odeslán o den dříve než měl být!', ); } public function testEmailDoesNotGetSent() { $this->set( BonusPointsExpiryEmail::class, $this->autowire(PointsExpiryEmailMock::class), ); $dbcfg = \Settings::getDefault(); $dbcfg->saveValue('bonus_program', [ 'expiry_email_time' => self::EXPIRY_EMAIL_TIME, 'remove_time' => self::REMOVE_TIME, ]); \Settings::clearCache(true); $listener = $this->get(CronListener::class); $listener->sendPointsExpiryEmails(); $this->assertCount( 1, PointsExpiryEmailMock::$payloads, 'E-mail o expiraci bodů nebyl odeslán!', ); } protected function getJsonDataSet($string): ArrayDataSet { $json = json_decode_strict($string, true); $twoDaysAgo = (new \DateTimeImmutable()) ->sub(new \DateInterval('P2D')) ->format('Y-m-d H:i:s'); $threeDaysAgo = (new \DateTimeImmutable()) ->sub(new \DateInterval('P3D')) ->format('Y-m-d H:i:s'); $removeTime = self::REMOVE_TIME; $notifyTime = self::EXPIRY_EMAIL_TIME; $exactlyNeededTime = (new \DateTimeImmutable()) ->add(new \DateInterval("P{$notifyTime}D")) ->sub(new \DateInterval("P{$removeTime}D")) ->format('Y-m-d H:i:s'); // meaning the user should be notified today // there is 60 day ($removeTime) difference between date_created and 14 days from now ($notifyTime) $sixteenDaysAgo = (new \DateTimeImmutable()) ->sub(new \DateInterval('P16D')) ->format('Y-m-d H:i:s'); $orders = &$json['orders']; $orders[0]['date_created'] = $threeDaysAgo; $orders[1]['date_created'] = $sixteenDaysAgo; $bonusPoints = &$json['bonus_points']; $bonusPoints[0]['date_created'] = $twoDaysAgo; $bonusPoints[3]['date_created'] = $exactlyNeededTime; return new ArrayDataSet($json); } protected function getDataSet() { return $this->getJsonDataSetFromFile(); } } class BonusComputerMock extends BonusComputer { public function getUsersWithoutOrdersInLastPub(int $days): array { return $this->getUsersWithoutOrdersInLast($days); } } class PointsExpiryEmailMock extends BonusPointsExpiryEmail { public static array $payloads = []; public function sendEmail($message) { self::$payloads[] = $message; return parent::sendEmail($message); } }