command for sending bulk sms with tests

This commit is contained in:
2022-06-14 01:15:58 +02:00
parent 4c0fef4f44
commit 28c952521f
15 changed files with 616 additions and 44 deletions

View File

@@ -0,0 +1,128 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\CalendarBundle\Tests\Service\ShortMessageNotification;
use ArrayIterator;
use Chill\CalendarBundle\Entity\Calendar;
use Chill\CalendarBundle\Service\ShortMessageNotification\BulkCalendarShortMessageSender;
use Chill\CalendarBundle\Service\ShortMessageNotification\CalendarForShortMessageProvider;
use Chill\CalendarBundle\Service\ShortMessageNotification\ShortMessageForCalendarBuilderInterface;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Service\ShortMessage\ShortMessage;
use Chill\MainBundle\Test\PrepareUserTrait;
use Chill\PersonBundle\DataFixtures\Helper\PersonRandomHelper;
use DateInterval;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use libphonenumber\PhoneNumberUtil;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Psr\Log\NullLogger;
use stdClass;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\MessageBusInterface;
/**
* @internal
* @coversNothing
*/
final class BulkCalendarShortMessageSenderTest extends KernelTestCase
{
use PersonRandomHelper;
use PrepareUserTrait;
use ProphecyTrait;
private array $toDelete = [];
protected function setUp(): void
{
parent::setUp();
self::bootKernel();
}
protected function tearDown(): void
{
self::bootKernel();
$em = self::$container->get(EntityManagerInterface::class);
foreach ($this->toDelete as [$entity, $id]) {
$entity = $em->find($entity, $id);
$em->remove($entity);
}
$em->flush();
}
public function testSendBulkMessageToEligibleCalendar()
{
$em = self::$container->get(EntityManagerInterface::class);
$calendar = new Calendar();
$calendar
->addPerson($this->getRandomPerson($em))
->setMainUser($user = $this->prepareUser([]))
->setStartDate(new DateTimeImmutable('now'))
->setEndDate($calendar->getStartDate()->add(new DateInterval('PT30M')))
->setSendSMS(true);
$user->setUsername(uniqid());
$user->setEmail(uniqid() . '@gmail.com');
$calendar->getPersons()->first()->setAcceptSMS(true);
// hack to prevent side effect with messages
$calendar->preventEnqueueChanges = true;
$em->persist($user);
//$this->toDelete[] = [User::class, $user->getId()];
$em->persist($calendar);
//$this->toDelete[] = [Calendar::class, $calendar->getId()];
$em->flush();
$provider = $this->prophesize(CalendarForShortMessageProvider::class);
$provider->getCalendars(Argument::type(DateTimeImmutable::class))
->willReturn(new ArrayIterator([$calendar]));
$messageBuilder = $this->prophesize(ShortMessageForCalendarBuilderInterface::class);
$messageBuilder->buildMessageForCalendar(Argument::type(Calendar::class))
->willReturn(
[
new ShortMessage(
'content',
PhoneNumberUtil::getInstance()->parse('+32470123456', 'BE'),
ShortMessage::PRIORITY_MEDIUM
),
]
);
$bus = $this->prophesize(MessageBusInterface::class);
$bus->dispatch(Argument::type(ShortMessage::class))
->willReturn(new Envelope(new stdClass()))
->shouldBeCalledTimes(1);
$bulk = new BulkCalendarShortMessageSender(
$provider->reveal(),
$em,
new NullLogger(),
$bus->reveal(),
$messageBuilder->reveal()
);
$bulk->sendBulkMessageToEligibleCalendars();
$em->clear();
$calendar = $em->find(Calendar::class, $calendar->getId());
$this->assertEquals(Calendar::SMS_SENT, $calendar->getSmsStatus());
}
}

View File

@@ -0,0 +1,103 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\CalendarBundle\Tests\Service\ShortMessageNotification;
use Chill\CalendarBundle\Entity\Calendar;
use Chill\CalendarBundle\Repository\CalendarRepository;
use Chill\CalendarBundle\Service\ShortMessageNotification\CalendarForShortMessageProvider;
use Chill\CalendarBundle\Service\ShortMessageNotification\DefaultRangeGenerator;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use function count;
/**
* @internal
* @coversNothing
*/
final class CalendarForShortMessageProviderTest extends TestCase
{
use ProphecyTrait;
public function testGetCalendars()
{
$calendarRepository = $this->prophesize(CalendarRepository::class);
$calendarRepository->findByNotificationAvailable(
Argument::type(DateTimeImmutable::class),
Argument::type(DateTimeImmutable::class),
Argument::type('int'),
Argument::exact(0)
)->will(static function ($args) {
return array_fill(0, $args[2], new Calendar());
})->shouldBeCalledTimes(1);
$calendarRepository->findByNotificationAvailable(
Argument::type(DateTimeImmutable::class),
Argument::type(DateTimeImmutable::class),
Argument::type('int'),
Argument::not(0)
)->will(static function ($args) {
return array_fill(0, $args[2] - 1, new Calendar());
})->shouldBeCalledTimes(1);
$em = $this->prophesize(EntityManagerInterface::class);
$em->clear()->shouldBeCalled();
$provider = new CalendarForShortMessageProvider(
$calendarRepository->reveal(),
$em->reveal(),
new DefaultRangeGenerator()
);
$calendars = iterator_to_array($provider->getCalendars(new DateTimeImmutable('now')));
$this->assertGreaterThan(1, count($calendars));
$this->assertLessThan(100, count($calendars));
$this->assertContainsOnly(Calendar::class, $calendars);
}
public function testGetCalendarsWithOnlyOneCalendar()
{
$calendarRepository = $this->prophesize(CalendarRepository::class);
$calendarRepository->findByNotificationAvailable(
Argument::type(DateTimeImmutable::class),
Argument::type(DateTimeImmutable::class),
Argument::type('int'),
Argument::exact(0)
)->will(static function ($args) {
return array_fill(0, 1, new Calendar());
})->shouldBeCalledTimes(1);
$calendarRepository->findByNotificationAvailable(
Argument::type(DateTimeImmutable::class),
Argument::type(DateTimeImmutable::class),
Argument::type('int'),
Argument::not(0)
)->will(static function ($args) {
return [];
})->shouldBeCalledTimes(1);
$em = $this->prophesize(EntityManagerInterface::class);
$em->clear()->shouldBeCalled();
$provider = new CalendarForShortMessageProvider(
$calendarRepository->reveal(),
$em->reveal(),
new DefaultRangeGenerator()
);
$calendars = iterator_to_array($provider->getCalendars(new DateTimeImmutable('now')));
$this->assertEquals(1, count($calendars));
$this->assertContainsOnly(Calendar::class, $calendars);
}
}

View File

@@ -83,7 +83,12 @@ final class DefaultRangeGeneratorTest extends TestCase
['startDate' => $actualStartDate, 'endDate' => $actualEndDate] = $generator->generateRange($date);
$this->assertEquals($startDate->format(DateTimeImmutable::ATOM), $actualStartDate->format(DateTimeImmutable::ATOM));
$this->assertEquals($endDate->format(DateTimeImmutable::ATOM), $actualEndDate->format(DateTimeImmutable::ATOM));
if (null === $startDate) {
$this->assertNull($actualStartDate);
$this->assertNull($actualEndDate);
} else {
$this->assertEquals($startDate->format(DateTimeImmutable::ATOM), $actualStartDate->format(DateTimeImmutable::ATOM));
$this->assertEquals($endDate->format(DateTimeImmutable::ATOM), $actualEndDate->format(DateTimeImmutable::ATOM));
}
}
}

View File

@@ -0,0 +1,108 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\CalendarBundle\Tests\Service\ShortMessageNotification;
use Chill\CalendarBundle\Entity\Calendar;
use Chill\CalendarBundle\Service\ShortMessageNotification\DefaultShortMessageForCalendarBuilder;
use Chill\MainBundle\Entity\Location;
use Chill\MainBundle\Entity\User;
use Chill\PersonBundle\Entity\Person;
use DateInterval;
use DateTimeImmutable;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\Templating\EngineInterface;
/**
* @internal
* @coversNothing
*/
final class DefaultShortMessageForCalendarBuilderTest extends TestCase
{
use ProphecyTrait;
private PhoneNumberUtil $phoneNumberUtil;
protected function setUp(): void
{
$this->phoneNumberUtil = PhoneNumberUtil::getInstance();
}
public function testBuildMessageForCalendar()
{
$calendar = new Calendar();
$calendar
->setStartDate(new DateTimeImmutable('now'))
->setEndDate($calendar->getStartDate()->add(new DateInterval('PT30M')))
->setMainUser($user = new User())
->addPerson($person = new Person())
->setSendSMS(false);
$user
->setLabel('Alex')
->setMainLocation($location = new Location());
$location->setName('LOCAMAT');
$person
->setMobilenumber($this->phoneNumberUtil->parse('+32470123456', 'BE'))
->setAcceptSMS(false);
$engine = $this->prophesize(EngineInterface::class);
$engine->render(Argument::exact('@ChillCalendar/CalendarShortMessage/short_message.txt.twig'), Argument::withKey('calendar'))
->willReturn('message content')
->shouldBeCalledTimes(1);
$engine->render(Argument::exact('@ChillCalendar/CalendarShortMessage/short_message_canceled.txt.twig'), Argument::withKey('calendar'))
->willReturn('message canceled')
->shouldBeCalledTimes(1);
$builder = new DefaultShortMessageForCalendarBuilder(
$engine->reveal()
);
// if the calendar should not send sms
$sms = $builder->buildMessageForCalendar($calendar);
$this->assertCount(0, $sms);
// if the person do not accept sms
$calendar->setSendSMS(true);
$sms = $builder->buildMessageForCalendar($calendar);
$this->assertCount(0, $sms);
// person accepts sms
$person->setAcceptSMS(true);
$sms = $builder->buildMessageForCalendar($calendar);
$this->assertCount(1, $sms);
$this->assertEquals(
'+32470123456',
$this->phoneNumberUtil->format($sms[0]->getPhoneNumber(), PhoneNumberFormat::E164)
);
$this->assertEquals('message content', $sms[0]->getContent());
$this->assertEquals('low', $sms[0]->getPriority());
// if the calendar is canceled
$calendar
->setSmsStatus(Calendar::SMS_SENT)
->setStatus(Calendar::STATUS_CANCELED);
$sms = $builder->buildMessageForCalendar($calendar);
$this->assertCount(1, $sms);
$this->assertEquals(
'+32470123456',
$this->phoneNumberUtil->format($sms[0]->getPhoneNumber(), PhoneNumberFormat::E164)
);
$this->assertEquals('message canceled', $sms[0]->getContent());
$this->assertEquals('low', $sms[0]->getPriority());
}
}