Browse Source

tests & refactoring

Vincent GUFFON 3 years ago
parent
commit
4c4ad531e6

+ 7 - 7
src/Entity/Message/Email.php

@@ -34,7 +34,7 @@ class Email extends AbstractMessage
     private Access $author;
     private Access $author;
 
 
     #[ORM\OneToMany(mappedBy: 'email', targetEntity: ReportEmail::class, cascade: ['persist'], orphanRemoval: true)]
     #[ORM\OneToMany(mappedBy: 'email', targetEntity: ReportEmail::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $report;
+    private Collection $reports;
 
 
     #[ORM\ManyToOne(cascade: ['persist'])]
     #[ORM\ManyToOne(cascade: ['persist'])]
     #[ORM\JoinColumn(nullable: true)]
     #[ORM\JoinColumn(nullable: true)]
@@ -55,7 +55,7 @@ class Email extends AbstractMessage
     public function __construct()
     public function __construct()
     {
     {
         $this->uuid = Uuid::uuid4();
         $this->uuid = Uuid::uuid4();
-        $this->report = new ArrayCollection();
+        $this->reports = new ArrayCollection();
         $this->files = new ArrayCollection();
         $this->files = new ArrayCollection();
         $this->tags = new ArrayCollection();
         $this->tags = new ArrayCollection();
     }
     }
@@ -99,15 +99,15 @@ class Email extends AbstractMessage
     /**
     /**
      * @return Collection<int, ReportEmail>
      * @return Collection<int, ReportEmail>
      */
      */
-    public function getReport(): Collection
+    public function getReports(): Collection
     {
     {
-        return $this->report;
+        return $this->reports;
     }
     }
 
 
     public function addReport(ReportEmail $report): self
     public function addReport(ReportEmail $report): self
     {
     {
-        if (!$this->report->contains($report)) {
-            $this->report[] = $report;
+        if (!$this->reports->contains($report)) {
+            $this->reports[] = $report;
             $report->setEmail($this);
             $report->setEmail($this);
         }
         }
 
 
@@ -116,7 +116,7 @@ class Email extends AbstractMessage
 
 
     public function removeReport(ReportEmail $report): self
     public function removeReport(ReportEmail $report): self
     {
     {
-        if ($this->report->removeElement($report)) {
+        if ($this->reports->removeElement($report)) {
             // set the owning side to null (unless already changed)
             // set the owning side to null (unless already changed)
             if ($report->getEmail() === $this) {
             if ($report->getEmail() === $this) {
                 $report->setEmail(null);
                 $report->setEmail(null);

+ 1 - 1
src/Entity/Message/ReportEmail.php

@@ -19,7 +19,7 @@ class ReportEmail extends AbstractReport
     #[ORM\GeneratedValue]
     #[ORM\GeneratedValue]
     private ?int $id = null;
     private ?int $id = null;
 
 
-    #[ORM\ManyToOne(inversedBy: 'report')]
+    #[ORM\ManyToOne(inversedBy: 'reports')]
     #[ORM\JoinColumn('message_id')]
     #[ORM\JoinColumn('message_id')]
     private Email $email;
     private Email $email;
 
 

+ 1 - 1
src/Entity/Message/ReportSms.php

@@ -19,7 +19,7 @@ class ReportSms extends AbstractReport
     #[ORM\GeneratedValue]
     #[ORM\GeneratedValue]
     private ?int $id = null;
     private ?int $id = null;
 
 
-    #[ORM\ManyToOne(inversedBy: 'report')]
+    #[ORM\ManyToOne(inversedBy: 'reports')]
     #[ORM\JoinColumn('message_id')]
     #[ORM\JoinColumn('message_id')]
     private Sms $sms;
     private Sms $sms;
 
 

+ 11 - 2
src/Service/Mailer/Builder/AbstractBuilder.php

@@ -11,6 +11,7 @@ use App\Repository\Core\ContactPointRepository;
 use App\Service\Mailer\Email;
 use App\Service\Mailer\Email;
 use App\Entity\Message\Email as EmailEntity;
 use App\Entity\Message\Email as EmailEntity;
 use App\Service\Mailer\EmailRecipient;
 use App\Service\Mailer\EmailRecipient;
+use App\Tests\Service\Mailer\Builder\AbstractBuilderTest;
 use Symfony\Contracts\Service\Attribute\Required;
 use Symfony\Contracts\Service\Attribute\Required;
 use Twig\Environment;
 use Twig\Environment;
 
 
@@ -36,6 +37,7 @@ class AbstractBuilder implements AbstractBuilderInterface
      * @param Access $author
      * @param Access $author
      * @param string $content
      * @param string $content
      * @return EmailEntity
      * @return EmailEntity
+     * @see AbstractBuilderTest::testBuildEmailEntity()
      */
      */
     public function buildEmailEntity(string $subject, Access $author, string $content): EmailEntity{
     public function buildEmailEntity(string $subject, Access $author, string $content): EmailEntity{
         return (new EmailEntity())
         return (new EmailEntity())
@@ -57,6 +59,8 @@ class AbstractBuilder implements AbstractBuilderInterface
      * @throws \Twig_Error_Loader
      * @throws \Twig_Error_Loader
      * @throws \Twig_Error_Runtime
      * @throws \Twig_Error_Runtime
      * @throws \Twig_Error_Syntax
      * @throws \Twig_Error_Syntax
+     *
+     * @see AbstractBuilderTest::testRender()
      */
      */
     public function render(string $template, array $context)
     public function render(string $template, array $context)
     {
     {
@@ -68,6 +72,8 @@ class AbstractBuilder implements AbstractBuilderInterface
      * @param Access|Organization|string $target
      * @param Access|Organization|string $target
      * @param string $sendType
      * @param string $sendType
      * @param string|null $contactPointType
      * @param string|null $contactPointType
+     *
+     * @see AbstractBuilderTest::testAddRecipient()
      */
      */
     public function addRecipient(Email $email, Access|Organization|string $target, string $sendType, string $contactPointType = null): void{
     public function addRecipient(Email $email, Access|Organization|string $target, string $sendType, string $contactPointType = null): void{
         $emailRecipient = (new EmailRecipient())
         $emailRecipient = (new EmailRecipient())
@@ -92,6 +98,8 @@ class AbstractBuilder implements AbstractBuilderInterface
     /**
     /**
      * @param array $contactPoints
      * @param array $contactPoints
      * @param EmailRecipient $recipient
      * @param EmailRecipient $recipient
+     *
+     * @see AbstractBuilderTest::testSetMailToRecipient()
      */
      */
     public function setMailToRecipient(array $contactPoints, EmailRecipient $recipient): void {
     public function setMailToRecipient(array $contactPoints, EmailRecipient $recipient): void {
         if($contactPoint = $this->getFirstContactPointWithEmail($contactPoints)){
         if($contactPoint = $this->getFirstContactPointWithEmail($contactPoints)){
@@ -105,8 +113,10 @@ class AbstractBuilder implements AbstractBuilderInterface
     /**
     /**
      * @param $contactPoints
      * @param $contactPoints
      * @return ContactPoint
      * @return ContactPoint
+     *
+     * @see AbstractBuilderTest::testGetFirstContactPointWithEmail()
      */
      */
-    public function getFirstContactPointWithEmail($contactPoints): ContactPoint{
+    public function getFirstContactPointWithEmail($contactPoints): ?ContactPoint{
         $find = false;
         $find = false;
         $cmpt = 0;
         $cmpt = 0;
         $contactPoint = null;
         $contactPoint = null;
@@ -118,7 +128,6 @@ class AbstractBuilder implements AbstractBuilderInterface
             }
             }
             $cmpt++;
             $cmpt++;
         }
         }
-
         return $contactPoint;
         return $contactPoint;
     }
     }
 }
 }

+ 106 - 56
src/Service/Mailer/Mailer.php

@@ -12,6 +12,7 @@ use App\Service\ServiceIterator\Mailer\BuilderIterator;
 use App\Service\Utils\Environnement;
 use App\Service\Utils\Environnement;
 use App\Service\Utils\StringsUtils;
 use App\Service\Utils\StringsUtils;
 use App\Enum\Message\ReportMessageStatusEnum;
 use App\Enum\Message\ReportMessageStatusEnum;
+use App\Tests\Service\Mailer\MailerTest;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\ORM\EntityManagerInterface;
 use Doctrine\ORM\EntityManagerInterface;
 use Psr\Log\LoggerInterface;
 use Psr\Log\LoggerInterface;
@@ -46,6 +47,8 @@ class Mailer
      *
      *
      * @param MailerModelInterface $mailerModel
      * @param MailerModelInterface $mailerModel
      * @throws \Exception
      * @throws \Exception
+     *
+     * @see MailerTest::testMain()
      */
      */
     public function main(MailerModelInterface $mailerModel): ArrayCollection{
     public function main(MailerModelInterface $mailerModel): ArrayCollection{
         $builderService = $this->builderIterator->getBuilderFor($mailerModel);
         $builderService = $this->builderIterator->getBuilderFor($mailerModel);
@@ -56,7 +59,7 @@ class Mailer
         /** @var Email $email */
         /** @var Email $email */
         foreach ($emailsCollection as $email){
         foreach ($emailsCollection as $email){
             //si l'email n'a pas de destinataire, on ne l'envoi pas...
             //si l'email n'a pas de destinataire, on ne l'envoi pas...
-            if(empty($email->getEmailRecipients())){
+            if($email->getEmailRecipients()->isEmpty()){
                 $email->getEmailEntity()->setStatus(MessageStatusEnum::NO_RECIPIENT()->getValue());
                 $email->getEmailEntity()->setStatus(MessageStatusEnum::NO_RECIPIENT()->getValue());
                 continue;
                 continue;
             }
             }
@@ -66,11 +69,10 @@ class Mailer
 
 
             //Persistance de l'entité Email
             //Persistance de l'entité Email
             $this->persistEmailEntity($email);
             $this->persistEmailEntity($email);
-
         }
         }
 
 
         //Envoi du rapport
         //Envoi du rapport
-        $this->report($emailsCollection);
+        $this->sendReport($emailsCollection);
 
 
         $this->entityManager->flush();
         $this->entityManager->flush();
 
 
@@ -80,6 +82,8 @@ class Mailer
     /**
     /**
      * Fonction d'envoie
      * Fonction d'envoie
      * @param EmailInterface $email
      * @param EmailInterface $email
+     *
+     * @see MailerTest::testSend()
      */
      */
     public function send(EmailInterface $email): void{
     public function send(EmailInterface $email): void{
         //On créer le mail
         //On créer le mail
@@ -94,7 +98,6 @@ class Mailer
         // @todo
         // @todo
         //$this->addAttachments();
         //$this->addAttachments();
 
 
-
         //On tente d'envoyer
         //On tente d'envoyer
         try {
         try {
             $this->symfonyMailer->send($symfonyMail);
             $this->symfonyMailer->send($symfonyMail);
@@ -109,10 +112,76 @@ class Mailer
     }
     }
 
 
     /**
     /**
-     * Fonction de rapport
+     * Envoie le rapport d'envoi
+     * @param ArrayCollection $emails
+     *
+     * @see MailerTest::testSendReport()
+     */
+    public function sendReport(ArrayCollection $emails): void{
+        $reportEmail = $this->createReportEmail($emails);
+        try {
+            $this->symfonyMailer->send($reportEmail);
+        } catch (TransportExceptionInterface $e) {
+            $this->logger->error('Error while sending report');
+            $this->logger->error($e);
+        }
+    }
+
+    /**
+     * Création du Mail qui sera envoyé via le Mailer de Symfony
+     * @param Email $email
+     * @return SymfonyEmail
+     *
+     * @see MailerTest::testCreateSymfonyEmail()
+     */
+    public function createSymfonyEmail(Email $email): SymfonyEmail{
+        $addressMailFrom = new Address($email->getFrom(), $email->getEmailEntity()->getAuthor()->getPerson()->getFullName());
+
+        return (new SymfonyEmail())
+            ->from($addressMailFrom)
+            ->replyTo($addressMailFrom)
+            ->returnPath(Address::create("mail.report@opentalent.fr"))
+            ->subject($email->getEmailEntity()->getAbout())
+            ->html($email->getContent())
+            ->text($this->stringsUtils->convertHtmlToText($email->getContent()))
+            ;
+    }
+
+    /**
+     * Créer le Templated Email contenant le rapport d'envoi
+     * @param ArrayCollection $emails
+     * @return object|TemplatedEmail
+     *
+     * @see MailerTest::testCreateReportEmail()
+     */
+    public function createReportEmail(ArrayCollection $emails){
+        [$delivered, $unDelivered] = $this->getDeliveredAndUndelivered($emails);
+
+        /** @var Email $email */
+        $email = $emails->first();
+        return (new TemplatedEmail())
+            ->from($this->opentalentNoReplyEmailAddress)
+            ->subject(sprintf('Rapport d\'envoi du message : %s', $email->getEmailEntity()->getAbout()))
+            ->htmlTemplate('@templates/emails/report.html.twig')
+            ->context(
+                [
+                    'email_example' => $email->getEmailEntity(),
+                    'delivered' => $delivered,
+                    'unDelivered' => $unDelivered
+                ]
+            )
+            ->addTo(new Address($email->getFrom(), $email->getEmailEntity()->getAuthor()->getPerson()->getFullName()))
+        ;
+    }
+
+    /**
+     * Récupère les recipient delivered & undelivered de l'ensemble des emails
      * @param ArrayCollection $emails
      * @param ArrayCollection $emails
+     * @return array[]
+     *
+     * @see MailerTest::testGetDeliveredAndUndelivered()
      */
      */
-    public function report(ArrayCollection $emails): void{
+    function getDeliveredAndUndelivered(ArrayCollection $emails): array {
         $delivered = [];
         $delivered = [];
         $unDelivered = [];
         $unDelivered = [];
 
 
@@ -127,53 +196,45 @@ class Mailer
                 }
                 }
             }
             }
         }
         }
-
-        $templatedMail = (new TemplatedEmail())
-            ->from($this->opentalentNoReplyEmailAddress)
-            ->subject(sprintf('Rapport d\'envoi du message : %s', $emails->first()->getEmailEntity()->getAbout()))
-            ->htmlTemplate('@templates/emails/report.html.twig')
-            ->context(
-                [
-                    'email_example' => $emails->first()->getEmailEntity(),
-                    'delivered' => $delivered,
-                    'unDelivered' => $unDelivered
-                ]
-            )
-            ->addTo(new Address($this->opentalentNoReplyEmailAddress))
-        ;
-
-        try {
-            $this->symfonyMailer->send($templatedMail);
-        } catch (TransportExceptionInterface $e) {
-            $this->logger->error('Error while sending report');
-            $this->logger->error($e);
-        }
+        return [$delivered, $unDelivered];
     }
     }
 
 
     /**
     /**
-     * Persist l'Email et les ReportEmail
+     * Persist l'Email
      * @param Email $email
      * @param Email $email
+     *
+     * @see MailerTest::testPersistEmailEntity()
      */
      */
     public function persistEmailEntity(Email $email){
     public function persistEmailEntity(Email $email){
         $emailEntity = $email->getEmailEntity();
         $emailEntity = $email->getEmailEntity();
-
         /** @var EmailRecipient $emailRecipient */
         /** @var EmailRecipient $emailRecipient */
         foreach ($email->getEmailRecipients() as $emailRecipient){
         foreach ($email->getEmailRecipients() as $emailRecipient){
-            $report = (new ReportEmail())
-                ->setAddressEmail($emailRecipient->getEmailAddress())
-                ->setAccess($emailRecipient->getAccess())
-                ->setOrganization($emailRecipient->getOrganization())
-                ->setDateSend(new \DateTime('now'))
-                ->setStatus($emailRecipient->getSendStatus())
-            ;
-            $emailEntity->addReport($report);
+            $emailEntity->addReport($this->createReport($emailRecipient));
         }
         }
         $this->entityManager->persist($emailEntity);
         $this->entityManager->persist($emailEntity);
     }
     }
 
 
+    /**
+     * Création du rapport
+     * @param EmailRecipient $emailRecipient
+     *
+     * @see MailerTest::testCreateReport()
+     */
+    public function createReport(EmailRecipient $emailRecipient): ReportEmail{
+        return (new ReportEmail())
+            ->setAddressEmail($emailRecipient->getEmailAddress())
+            ->setAccess($emailRecipient->getAccess())
+            ->setOrganization($emailRecipient->getOrganization())
+            ->setDateSend(new \DateTime('now'))
+            ->setStatus($emailRecipient->getSendStatus())
+        ;
+    }
+
     /**
     /**
      * Reduit le nombre d'emails a envoyer si on ne se trouve pas en prod
      * Reduit le nombre d'emails a envoyer si on ne se trouve pas en prod
      * @param ArrayCollection $emailsCollection
      * @param ArrayCollection $emailsCollection
+     *
+     * @see MailerTest::testReduceEmailsCollectionInPreproduction()
      */
      */
     public function reduceEmailsCollectionInPreproduction(ArrayCollection $emailsCollection): ArrayCollection {
     public function reduceEmailsCollectionInPreproduction(ArrayCollection $emailsCollection): ArrayCollection {
         if($this->environnement->get(EnvironnementVarEnum::APP_ENV()->getValue()) !== 'prod') {
         if($this->environnement->get(EnvironnementVarEnum::APP_ENV()->getValue()) !== 'prod') {
@@ -187,6 +248,8 @@ class Mailer
     /**
     /**
      * @param SymfonyEmail $symfonyMail
      * @param SymfonyEmail $symfonyMail
      * @param Email $email
      * @param Email $email
+     *
+     * @see MailerTest::testAddHeaders()
      */
      */
     public function addHeaders(SymfonyEmail $symfonyMail, Email $email){
     public function addHeaders(SymfonyEmail $symfonyMail, Email $email){
         $symfonyMail->getHeaders()->addTextHeader('List-Unsubscribe','mailto:'.$email->getFrom().'?subject=désabonnement');
         $symfonyMail->getHeaders()->addTextHeader('List-Unsubscribe','mailto:'.$email->getFrom().'?subject=désabonnement');
@@ -197,6 +260,8 @@ class Mailer
      * On change le #__#ANTISPAM_PERSON_EMAIL#__# par la liste des emails afin d'éviter le spamming sur l'envoi en masse
      * On change le #__#ANTISPAM_PERSON_EMAIL#__# par la liste des emails afin d'éviter le spamming sur l'envoi en masse
      * @param Email $email
      * @param Email $email
      * @param array $to
      * @param array $to
+     *
+     * @see MailerTest::testSetAntiSpam()
      */
      */
     public function setAntiSpam(Email $email, array $addresses){
     public function setAntiSpam(Email $email, array $addresses){
         // map des Address pour ne conserver qu'un tableau d'email
         // map des Address pour ne conserver qu'un tableau d'email
@@ -207,35 +272,20 @@ class Mailer
         $email->setContent(str_replace('#__#ANTISPAM_PERSON_EMAIL#__#', implode(',', $to), $email->getContent()));
         $email->setContent(str_replace('#__#ANTISPAM_PERSON_EMAIL#__#', implode(',', $to), $email->getContent()));
     }
     }
 
 
-
-    /**
-     * Création du Mail qui sera envoyé via le Mailer de Symfony
-     * @param Email $email
-     * @return SymfonyEmail
-     */
-    public function createSymfonyEmail(Email $email): SymfonyEmail{
-        $addressMailFrom = new Address($email->getFrom(), $email->getEmailEntity()->getAuthor()->getPerson()->getFullName());
-
-        return (new SymfonyEmail())
-            ->from($addressMailFrom)
-            ->replyTo($addressMailFrom)
-            ->returnPath(Address::create("mail.report@opentalent.fr"))
-            ->subject($email->getEmailEntity()->getAbout())
-            ->html($email->getContent())
-            ->text($this->stringsUtils->convertHtmlToText($email->getContent()))
-            ;
-    }
-
     /**
     /**
      * On ajoute les destinataires suivant le type d'envoie souhaité
      * On ajoute les destinataires suivant le type d'envoie souhaité
      * @param SymfonyEmail $symfonyMail
      * @param SymfonyEmail $symfonyMail
      * @param Address $addressesMail
      * @param Address $addressesMail
+     *
+     * @see MailerTest::testAddRecipients()
      */
      */
     public function addRecipients(SymfonyEmail $symfonyMail, Email $email): void{
     public function addRecipients(SymfonyEmail $symfonyMail, Email $email): void{
         $allReadySend = [];
         $allReadySend = [];
 
 
         foreach ($email->getEmailRecipients() as $emailRecipient){
         foreach ($email->getEmailRecipients() as $emailRecipient){
+
             $addressMail = new Address($emailRecipient->getEmailAddress(), $emailRecipient->getName());
             $addressMail = new Address($emailRecipient->getEmailAddress(), $emailRecipient->getName());
+
             //On envoi pas en double
             //On envoi pas en double
             if(!in_array($addressMail, $allReadySend)){
             if(!in_array($addressMail, $allReadySend)){
                 $allReadySend[] = $addressMail;
                 $allReadySend[] = $addressMail;

+ 179 - 0
tests/Service/Mailer/Builder/AbstractBuilderTest.php

@@ -0,0 +1,179 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Tests\Service\Mailer\Builder;
+
+use App\Entity\Access\Access;
+use App\Entity\Core\ContactPoint;
+use App\Entity\Message\Email;
+use App\Entity\Organization\Organization;
+use App\Entity\Person\Person;
+use App\Enum\Core\ContactPointTypeEnum;
+use App\Enum\Core\EmailSendingTypeEnum;
+use App\Enum\Message\ReportMessageStatusEnum;
+use App\Repository\Core\ContactPointRepository;
+use App\Service\Mailer\Builder\AbstractBuilder;
+use App\Service\Mailer\EmailRecipient;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+use Twig\Environment;
+
+/**
+ * Classe AbstractBuilderTest qui test le service AbstractBuilder
+ */
+class AbstractBuilderTest extends TestCase
+{
+    private MockObject | ContactPointRepository $contactPointRepository;
+    private MockObject | Environment $twig;
+    private MockObject | Access $access;
+
+    public function setUp(): void {
+        $this->contactPointRepository = $this->getMockBuilder(ContactPointRepository::class)->disableOriginalConstructor()->getMock();
+        $this->twig = $this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock();
+        $this->access = $this->getMockBuilder(Access::class)->getMock();
+    }
+
+    /**
+     * AbstractBuilder mock maker
+     * @param string $methodUnderTest
+     * @return AbstractBuilder|MockObject
+     */
+    private function makeAbstractBuilderMock(string $methodUnderTest): AbstractBuilder | MockObject
+    {
+        $abstractBuilder = $this->getMockBuilder(AbstractBuilder::class)
+            ->setMethodsExcept(['setTwig', 'setContactPointRepository', $methodUnderTest])
+            ->getMock();
+
+        $abstractBuilder->setContactPointRepository($this->contactPointRepository);
+        $abstractBuilder->setTwig($this->twig);
+
+        return $abstractBuilder;
+    }
+
+    /**
+     * @see AbstractBuilder::buildEmailEntity()
+     */
+    public function testBuildEmailEntity(){
+        $abstractBuilder = $this->makeAbstractBuilderMock('buildEmailEntity');
+        $email = $abstractBuilder->buildEmailEntity('sujet', $this->access, 'contenu');
+
+        $this->assertInstanceOf(Email::class, $email);
+        $this->assertEquals('sujet', $email->getAbout());
+        $this->assertEquals('contenu', $email->getText());
+        $this->assertEquals($this->access, $email->getAuthor());
+        $this->assertTrue($email->getIsSystem());
+    }
+
+    /**
+     * @see AbstractBuilder::render()
+     */
+    public function testRender(){
+        $abstractBuilder = $this->makeAbstractBuilderMock('render');
+
+        $context = [];
+        $template = 'test';
+
+        $this->twig
+            ->expects(self::once())
+            ->method('render')
+            ->with(sprintf('@templates/emails/%s.html.twig', $template), $context);
+
+        $abstractBuilder->render($template, $context);
+    }
+
+    /**
+     * @see AbstractBuilder::addRecipient()
+     */
+    public function testAddRecipient(){
+        $abstractBuilder = $this->makeAbstractBuilderMock('addRecipient');
+        $sendType = EmailSendingTypeEnum::TO()->getValue();
+
+        //Access Target
+        $person = $this->getMockBuilder(Person::class)->getMock();
+        $person->method('getFullName')->willReturn('Marc Durand');
+        $this->access->method('getPerson')->willReturn($person);
+
+        $email = new \App\Service\Mailer\Email();
+        $abstractBuilder->addRecipient($email, $this->access, $sendType, ContactPointTypeEnum::PRINCIPAL()->getValue());
+
+        /** @var EmailRecipient $emailRecipient */
+        $emailRecipient = $email->getEmailRecipients()->first();
+        $this->assertEquals($sendType, $emailRecipient->getSendType());
+        $this->assertEquals($person->getFullName(), $emailRecipient->getName());
+        $this->assertEquals($this->access, $emailRecipient->getAccess());
+
+        //Organization Target
+        $organization = $this->getMockBuilder(Organization::class)->getMock();
+        $organization->method('getName')->willReturn('Test');
+
+        $email = new \App\Service\Mailer\Email();
+        $abstractBuilder->addRecipient($email, $organization, $sendType, ContactPointTypeEnum::PRINCIPAL()->getValue());
+
+        /** @var EmailRecipient $emailRecipient */
+        $emailRecipient = $email->getEmailRecipients()->first();
+        $this->assertEquals($organization, $emailRecipient->getOrganization());
+        $this->assertEquals($organization->getName(), $emailRecipient->getName());
+
+        //Custom Target
+        $custom = "foo.bar@opentalent.fr";
+        $email = new \App\Service\Mailer\Email();
+        $abstractBuilder->addRecipient($email, $custom, $sendType, ContactPointTypeEnum::PRINCIPAL()->getValue());
+
+        /** @var EmailRecipient $emailRecipient */
+        $emailRecipient = $email->getEmailRecipients()->first();
+        $this->assertEquals($custom, $emailRecipient->getEmailAddress());
+        $this->assertEquals(ReportMessageStatusEnum::DELIVERED()->getValue(), $emailRecipient->getSendStatus());
+    }
+
+    /**
+     * @see AbstractBuilder::setMailToRecipient()
+     */
+    public function testSetMailToRecipientWithoutEmail(){
+        $abstractBuilder = $this->makeAbstractBuilderMock('setMailToRecipient');
+        $contactPoint = $this->getMockBuilder(ContactPoint::class)->getMock();
+        $abstractBuilder->method('getFirstContactPointWithEmail')->willReturn(null);
+
+        $emailRecipient = new EmailRecipient();
+        $abstractBuilder->setMailToRecipient([$contactPoint], $emailRecipient);
+
+        $this->assertEquals(ReportMessageStatusEnum::MISSING()->getValue(), $emailRecipient->getSendStatus());
+    }
+
+    /**
+     * @see AbstractBuilder::setMailToRecipient()
+     */
+    public function testSetMailToRecipientWithEmail(){
+        $abstractBuilder = $this->makeAbstractBuilderMock('setMailToRecipient');
+        $contactPoint = $this->getMockBuilder(ContactPoint::class)->getMock();
+
+        $emailRecipient = new EmailRecipient();
+        $contactPoint->method('getEmail')->willReturn('foo.bar@opentalent.fr');
+        $abstractBuilder->method('getFirstContactPointWithEmail')->willReturn($contactPoint);
+        $abstractBuilder->setMailToRecipient([$contactPoint], $emailRecipient);
+
+        $this->assertEquals(ReportMessageStatusEnum::DELIVERED()->getValue(), $emailRecipient->getSendStatus());
+        $this->assertEquals('foo.bar@opentalent.fr', $emailRecipient->getEmailAddress());
+    }
+
+    /**
+     * @see AbstractBuilder::getFirstContactPointWithEmail()
+     */
+    public function testGetFirstContactPointWithEmail(){
+        $abstractBuilder = $this->makeAbstractBuilderMock('getFirstContactPointWithEmail');
+
+        $contactPoint = $this->getMockBuilder(ContactPoint::class)->getMock();
+        $contactPoint->method('getEmail')->willReturn('foo.bar@opentalent.fr');
+
+        $abstractBuilder->getFirstContactPointWithEmail([$contactPoint]);
+
+        $this->assertEquals('foo.bar@opentalent.fr', $contactPoint->getEmail());
+
+        $contactPoint2 = $this->getMockBuilder(ContactPoint::class)->getMock();
+        $contactPoint->method('getEmail')->willReturn(null);
+        $contactPoint2->method('getEmail')->willReturn('foo.bar@opentalent.fr');
+
+        $abstractBuilder->getFirstContactPointWithEmail([$contactPoint, $contactPoint2]);
+
+        $this->assertEquals('foo.bar@opentalent.fr', $contactPoint->getEmail());
+    }
+}

+ 397 - 0
tests/Service/Mailer/MailerTest.php

@@ -0,0 +1,397 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Tests\Service\Mailer;
+
+use App\Entity\Access\Access;
+use App\Entity\Message\ReportEmail;
+use App\Entity\Person\Person;
+use App\Enum\Core\EmailSendingTypeEnum;
+use App\Enum\Message\MessageStatusEnum;
+use App\Enum\Message\ReportMessageStatusEnum;
+use App\Service\Mailer\Builder\BuilderInterface;
+use App\Service\Mailer\Email;
+use App\Service\Mailer\EmailRecipient;
+use App\Service\Mailer\Mailer;
+use App\Service\Mailer\Model\MailerModelInterface;
+use App\Service\ServiceIterator\Mailer\BuilderIterator;
+use App\Service\Utils\Environnement;
+use App\Service\Utils\StringsUtils;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\ORM\EntityManagerInterface;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+use Psr\Log\LoggerInterface;
+use Ramsey\Uuid\Uuid;
+use Symfony\Bridge\Twig\Mime\TemplatedEmail;
+use Symfony\Component\Mailer\MailerInterface;
+use Symfony\Component\Mime\Address;
+use Symfony\Component\Mime\Email as SymfonyEmail;
+
+/**
+ * Classe MailerTest qui test le service Mailer
+ */
+class MailerTest extends TestCase
+{
+    private string $opentalentNoReplyEmailAddress;
+    private MockObject | MailerInterface $symfonyMailer;
+    private MockObject | BuilderIterator $builderIterator;
+    private MockObject | StringsUtils $stringsUtils;
+    private MockObject | EntityManagerInterface $entityManager;
+    private MockObject | Environnement $environnement;
+    private MockObject | LoggerInterface $logger;
+
+    public function setUp(): void {
+        $this->symfonyMailer = $this->getMockBuilder(MailerInterface::class)->disableOriginalConstructor()->getMock();
+        $this->opentalentNoReplyEmailAddress = 'noreply@opentalent.fr';
+        $this->builderIterator = $this->getMockBuilder(BuilderIterator::class)->disableOriginalConstructor()->getMock();
+        $this->stringsUtils = $this->getMockBuilder(StringsUtils::class)->disableOriginalConstructor()->getMock();
+        $this->entityManager = $this->getMockBuilder(EntityManagerInterface::class)->disableOriginalConstructor()->getMock();
+        $this->environnement = $this->getMockBuilder(Environnement::class)->disableOriginalConstructor()->getMock();
+        $this->logger = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock();
+    }
+
+    /**
+     * mailer mock maker
+     * @param string $methodUnderTest
+     * @return Mailer|MockObject
+     */
+    private function makeMailerMock(string $methodUnderTest): Mailer | MockObject
+    {
+        $mailer = $this->getMockBuilder(Mailer::class)
+            ->setConstructorArgs([
+                $this->symfonyMailer,
+                $this->opentalentNoReplyEmailAddress,
+                $this->builderIterator,
+                $this->stringsUtils,
+                $this->entityManager,
+                $this->environnement,
+                $this->logger,
+            ])
+            ->setMethodsExcept([$methodUnderTest])
+            ->getMock();
+
+        return $mailer;
+    }
+
+    private function makeEmailEntity(): \App\Entity\Message\Email | MockObject{
+        $person = $this->getMockBuilder(Person::class)->disableOriginalConstructor()->getMock();
+        $person->method('getFullName')->willReturn('Ben Yolo');
+
+        $author = $this->getMockBuilder(Access::class)->disableOriginalConstructor()->getMock();
+        $author->method('getPerson')->willReturn($person);
+
+        $emailEntity = $this->getMockBuilder(\App\Entity\Message\Email::class)->disableOriginalConstructor()->getMock();
+        $emailEntity->method('getAuthor')->willReturn($author);
+        $emailEntity->method('getAbout')->willReturn('sujet');
+        $emailEntity->method('getUuid')->willReturn(Uuid::fromString('177ef0d8-6630-11ea-b69a-0242ac130003'));
+
+        return $emailEntity;
+    }
+
+    /**
+     * @see Mailer::main()
+     */
+    public function testMain(){
+        $mailer = $this->makeMailerMock('main');
+        $mailerModel = $this->getMockBuilder(MailerModelInterface::class)->disableOriginalConstructor()->getMock();
+        $builderService = $this->getMockBuilder(BuilderInterface::class)->disableOriginalConstructor()->getMock();
+
+        $email = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
+        $email->method('getEmailRecipients')->willReturn(new ArrayCollection());
+        $email->method('getEmailEntity')->willReturn(new \App\Entity\Message\Email());
+
+        $emailsCollection = new ArrayCollection([$email]);
+
+        $this->builderIterator
+            ->expects(self::once())
+            ->method('getBuilderFor')
+            ->willReturn($builderService);
+
+        $builderService
+            ->expects(self::once())
+            ->method('build')
+            ->with($mailerModel)
+            ->willReturn($emailsCollection)
+        ;
+
+        $mailer
+            ->expects(self::once())
+            ->method('reduceEmailsCollectionInPreproduction')
+            ->with($emailsCollection)
+            ->willReturn($emailsCollection)
+        ;
+
+        $mailer
+            ->expects(self::once())
+            ->method('sendReport')
+            ->with($emailsCollection)
+            ;
+
+        $this->entityManager
+            ->expects(self::once())
+            ->method('flush')
+        ;
+
+        $emailsCollection = $mailer->main($mailerModel);
+
+        $this->assertEquals(MessageStatusEnum::NO_RECIPIENT()->getValue(), $email->getEmailEntity()->getStatus());
+
+        $this->assertInstanceOf(Email::class, $emailsCollection->first());
+    }
+
+    /**
+     * @see Mailer::send()
+     */
+    public function testSend(){
+        $mailer = $this->makeMailerMock('send');
+
+        $email = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
+        $email->method('getEmailEntity')->willReturn(new \App\Entity\Message\Email());
+
+        $symfonyEmail = $this->getMockBuilder(SymfonyEmail::class)->disableOriginalConstructor()->getMock();
+        $symfonyEmail->method('getTo')->willReturn([]);
+
+        $mailer
+            ->expects(self::once())
+            ->method('createSymfonyEmail')
+            ->with($email)
+            ->willReturn($symfonyEmail)
+        ;
+
+        $mailer
+            ->expects(self::once())
+            ->method('addRecipients')
+            ->with($symfonyEmail, $email)
+        ;
+
+        $mailer
+            ->expects(self::once())
+            ->method('setAntiSpam')
+            ->with($email, $symfonyEmail->getTo())
+        ;
+
+        $mailer
+            ->expects(self::once())
+            ->method('addHeaders')
+            ->with($symfonyEmail, $email)
+        ;
+
+        $this->symfonyMailer
+            ->expects(self::once())
+            ->method('send')
+            ->with($symfonyEmail)
+        ;
+
+        $mailer->send($email);
+
+        $this->assertEquals(MessageStatusEnum::SEND()->getValue(), $email->getEmailEntity()->getStatus());
+    }
+
+    /**
+     * @see Mailer::sendReport()
+     */
+    public function testSendReport(){
+        $mailer = $this->makeMailerMock('sendReport');
+
+        $email = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
+        $templatedEmail = $this->getMockBuilder(TemplatedEmail::class)->disableOriginalConstructor()->getMock();
+
+        $mailer->method('createReportEmail')->willReturn($templatedEmail);
+        $this->symfonyMailer->expects(self::once())->method('send')->with($templatedEmail);
+
+        $mailer->sendReport(new ArrayCollection([$email]));
+    }
+
+    /**
+     * @see Mailer::createReportEmail()
+     */
+    public function testCreateReportEmail(){
+        $mailer = $this->makeMailerMock('createReportEmail');
+        $mailer->method('getDeliveredAndUndelivered')->willReturn([[], []]);
+
+        $emailEntity = $this->makeEmailEntity();
+
+        $email = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
+        $email->method('getEmailEntity')->willReturn($emailEntity);
+        $email->method('getFrom')->willReturn('foo.bar@opentalent.fr');
+
+        $reportEmail = $mailer->createReportEmail(new ArrayCollection([$email]));
+
+        $this->assertInstanceOf(TemplatedEmail::class, $reportEmail);
+    }
+
+    /**
+     * @see Mailer::getDeliveredAndUndelivered()
+     */
+    public function testGetDeliveredAndUndelivered(){
+        $mailer = $this->makeMailerMock('getDeliveredAndUndelivered');
+
+        $emailRecipient = $this->getMockBuilder(EmailRecipient::class)->disableOriginalConstructor()->getMock();
+        $emailRecipient->method('getSendStatus')->willReturn(ReportMessageStatusEnum::MISSING()->getValue());
+        $emailRecipient2 = $this->getMockBuilder(EmailRecipient::class)->disableOriginalConstructor()->getMock();
+        $emailRecipient2->method('getSendStatus')->willReturn(ReportMessageStatusEnum::DELIVERED()->getValue());
+        $email = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
+        $email->method('getEmailRecipients')->willReturn(new ArrayCollection([$emailRecipient, $emailRecipient2]));
+
+        $emailRecipient3 = $this->getMockBuilder(EmailRecipient::class)->disableOriginalConstructor()->getMock();
+        $emailRecipient3->method('getSendStatus')->willReturn(ReportMessageStatusEnum::DELIVERED()->getValue());
+        $emailRecipient4 = $this->getMockBuilder(EmailRecipient::class)->disableOriginalConstructor()->getMock();
+        $emailRecipient4->method('getSendStatus')->willReturn(ReportMessageStatusEnum::MISSING()->getValue());
+        $email2 = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
+        $email2->method('getEmailRecipients')->willReturn(new ArrayCollection([$emailRecipient3, $emailRecipient4]));
+
+        [$delivered, $undelivered] = $mailer->getDeliveredAndUndelivered(new ArrayCollection([$email, $email2]));
+
+        $this->assertCount(2, $delivered);
+        $this->assertCount(2, $undelivered);
+    }
+
+    /**
+     * @see Mailer::persistEmailEntity()
+     */
+    public function testPersistEmailEntity(){
+        $mailer = $this->makeMailerMock('persistEmailEntity');
+
+        $emailRecipient = $this->getMockBuilder(EmailRecipient::class)->disableOriginalConstructor()->getMock();
+        $emailRecipient2 = $this->getMockBuilder(EmailRecipient::class)->disableOriginalConstructor()->getMock();
+
+        $email = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
+        $emailEntity = $this->makeEmailEntity();
+
+        $email->method('getEmailEntity')->willReturn($emailEntity);
+        $email->method('getEmailRecipients')->willReturnOnConsecutiveCalls(new ArrayCollection([$emailRecipient, $emailRecipient2]));
+
+        $emailEntity->expects(self::exactly(2))->method('addReport');
+        $this->entityManager->expects(self::once())->method('persist')->with($emailEntity);
+
+        $mailer->persistEmailEntity($email);
+    }
+
+    /**
+     * @see Mailer::createReport()
+     */
+    public function testCreateReport(){
+        $mailer = $this->makeMailerMock('createReport');
+
+        $access = $this->getMockBuilder(Access::class)->disableOriginalConstructor()->getMock();
+
+        $emailRecipient = $this->getMockBuilder(EmailRecipient::class)->disableOriginalConstructor()->getMock();
+        $emailRecipient->method('getEmailAddress')->willReturn('foo.bar@opentalent.fr');
+        $emailRecipient->method('getName')->willReturn('Will Farel');
+        $emailRecipient->method('getSendType')->willReturn(EmailSendingTypeEnum::TO()->getValue());
+        $emailRecipient->method('getAccess')->willReturn($access);
+        $emailRecipient->method('getSendStatus')->willReturn(ReportMessageStatusEnum::DELIVERED()->getValue());
+
+        $report = $mailer->createReport($emailRecipient);
+
+        $this->assertInstanceOf(ReportEmail::class, $report);
+        $this->assertEquals('foo.bar@opentalent.fr', $report->getAddressEmail());
+        $this->assertEquals($access, $report->getAccess());
+        $this->assertEquals(ReportMessageStatusEnum::DELIVERED()->getValue(), $report->getStatus());
+    }
+
+    /**
+     * @see Mailer::reduceEmailsCollectionInPreproduction()
+     */
+    public function testReduceEmailsCollectionInPreproduction(){
+        $mailer = $this->makeMailerMock('reduceEmailsCollectionInPreproduction');
+        $environnement = $this->getMockBuilder(Environnement::class)->disableOriginalConstructor()->getMock();
+        $environnement->method('get')->willReturn('dev');
+
+        $array = [];
+        for($i=0; $i<=50; $i++){
+            $array[] = $i;
+        }
+
+        $arrayReduced = $mailer->reduceEmailsCollectionInPreproduction(new ArrayCollection($array));
+
+        $this->assertCount(20, $arrayReduced->toArray());
+    }
+
+    /**
+     * @see Mailer::addHeaders()
+     */
+    public function testAddHeaders(){
+        $mailer = $this->makeMailerMock('addHeaders');
+
+        $emailEntity = $this->makeEmailEntity();
+
+        $email = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
+        $email->method('getFrom')->willReturn('foo.bar@opentalent.fr');
+        $email->method('getEmailEntity')->willReturn($emailEntity);
+
+        $symfonyMail = new SymfonyEmail();
+
+        $mailer->addHeaders($symfonyMail, $email);
+
+        $this->assertEquals('mailto:foo.bar@opentalent.fr?subject=désabonnement', $symfonyMail->getHeaders()->get('List-Unsubscribe')->getBody());
+        $this->assertEquals('177ef0d8-6630-11ea-b69a-0242ac130003', $symfonyMail->getHeaders()->get('X-ID-OT')->getBody());
+    }
+
+    /**
+     * @see Mailer::setAntiSpam()
+     */
+    public function testSetAntiSpam(){
+        $mailer = $this->makeMailerMock('setAntiSpam');
+
+        $email = new Email();
+        $email->setContent('#__#ANTISPAM_PERSON_EMAIL#__#');
+
+        $addressMailFrom = new Address('foo.bar@opentalent.fr', 'Bob dit lane');
+
+        $mailer->setAntiSpam( $email, [$addressMailFrom]);
+
+        $this->assertEquals('foo.bar@opentalent.fr', $email->getContent());
+    }
+
+    /**
+     * @see Mailer::createSymfonyEmail()
+     */
+    public function testCreateSymfonyEmail(){
+        $mailer = $this->makeMailerMock('createSymfonyEmail');
+
+        $emailEntity = $this->makeEmailEntity();
+
+        $email = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
+        $email->method('getFrom')->willReturn('foo.bar@opentalent.fr');
+        $email->method('getEmailEntity')->willReturn($emailEntity);
+        $email->method('getContent')->willReturn('contenu');
+
+        $addressMailFrom = new Address($email->getFrom(), $email->getEmailEntity()->getAuthor()->getPerson()->getFullName());
+        $symfonyMail = $mailer->createSymfonyEmail($email);
+        $this->assertInstanceOf(SymfonyEmail::class, $symfonyMail);
+        $this->assertEquals($symfonyMail->getFrom(), [$addressMailFrom]);
+        $this->assertEquals($symfonyMail->getReplyTo(), [$addressMailFrom]);
+        $this->assertEquals($symfonyMail->getReturnPath(), Address::create("mail.report@opentalent.fr"));
+        $this->assertEquals($symfonyMail->getSubject(), $emailEntity->getAbout());
+        $this->assertEquals($symfonyMail->getHtmlBody(), $email->getContent());
+    }
+
+    /**
+     * @see Mailer::addRecipients()
+     */
+    public function testAddRecipients(){
+        $mailer = $this->makeMailerMock('addRecipients');
+        $symfonyMail = new SymfonyEmail();
+
+        $emailRecipient = $this->getMockBuilder(EmailRecipient::class)->disableOriginalConstructor()->getMock();
+        $emailRecipient->method('getEmailAddress')->willReturn('foo.bar@opentalent.fr');
+        $emailRecipient->method('getName')->willReturn('Will Farel');
+        $emailRecipient->method('getSendType')->willReturn(EmailSendingTypeEnum::TO()->getValue());
+
+        $emailRecipientBBC = $this->getMockBuilder(EmailRecipient::class)->disableOriginalConstructor()->getMock();
+        $emailRecipientBBC->method('getEmailAddress')->willReturn('foo.bar@opentalent.fr.bbc');
+        $emailRecipientBBC->method('getName')->willReturn('Will Farel');
+        $emailRecipientBBC->method('getSendType')->willReturn(EmailSendingTypeEnum::BBC()->getValue());
+
+        $email = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
+        $email->method('getEmailRecipients')->willReturn(new ArrayCollection([$emailRecipient, $emailRecipientBBC]));
+
+        $mailer->addRecipients($symfonyMail, $email);
+
+        $this->assertCount(1, $symfonyMail->getTo());
+        $this->assertCount(1, $symfonyMail->getBcc());
+        $this->assertCount(0, $symfonyMail->getCc());
+    }
+}