Procházet zdrojové kódy

add unittests for Notifier and MercureHub

Olivier Massot před 3 roky
rodič
revize
a66e983b7d

+ 14 - 8
src/Service/MercureHub.php

@@ -24,12 +24,21 @@ class MercureHub
     public const DELETE = 'delete';
 
     public function __construct(
-        private HubInterface $mercureHub,
-        private SerializerInterface $serializer,
-        private EncoderInterface $encoder,
+        private HubInterface          $hub,
+        private SerializerInterface   $serializer,
+        private EncoderInterface      $encoder,
         private IriConverterInterface $iriConverter
     ) {}
 
+    protected function createUpdate($accessId, string $data): Update
+    {
+        return new Update(
+            "access/{$accessId}",
+            $data,
+            true
+        );
+    }
+
     /**
      * Send an update to the
      *
@@ -49,12 +58,9 @@ class MercureHub
             'data' => $this->serializer->serialize($entity, 'jsonld')
         ], 'jsonld');
 
-        $update = new Update(
-            "access/{$accessId}",
-            $data,
-            true
+        $this->hub->publish(
+            $this->createUpdate($accessId, $data)
         );
-        $this->mercureHub->publish($update);
     }
 
     /**

+ 16 - 7
src/Service/Notifier.php

@@ -16,14 +16,13 @@ class Notifier
         private MercureHub $mercureHub
     ) {}
 
-    public function notify(
+    protected function createNotification(
         Access $access,
         string $name,
         string $type,
         array $message,
         string $link = null
-    ): Notification
-    {
+    ): Notification {
         $now = new \DateTime();
 
         $notification = new Notification();
@@ -35,6 +34,18 @@ class Notifier
             ->setLink($link)
             ->setCreateDate($now)
             ->setUpdateDate($now);
+        return $notification;
+    }
+
+    public function notify(
+        Access $access,
+        string $name,
+        string $type,
+        array $message,
+        string $link = null
+    ): Notification
+    {
+        $notification = $this->createNotification($access, $name, $type, $message, $link);
 
         $this->em->persist($notification);
         $this->em->flush();
@@ -73,16 +84,14 @@ class Notifier
 
     public function notifySystem(
         Access $access,
-        array $message,
-        string $link
+        array $message
     ): Notification
     {
         return $this->notify(
             $access,
             'message',
             NotificationTypeEnum::SYSTEM()->getValue(),
-            $message,
-            $link
+            $message
         );
     }
 

+ 140 - 0
tests/Service/MercureHubTest.php

@@ -0,0 +1,140 @@
+<?php
+
+namespace App\Tests\Service;
+
+use ApiPlatform\Core\Api\IriConverterInterface;
+use App\Service\MercureHub;
+use Doctrine\Entity;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Mercure\HubInterface;
+use Symfony\Component\Mercure\Update;
+use Symfony\Component\Serializer\Encoder\EncoderInterface;
+use Symfony\Component\Serializer\SerializerInterface;
+
+class TestableMercureHub extends MercureHub {
+    public function createUpdate($accessId, string $data): Update { return parent::createUpdate($accessId, $data); }
+}
+
+class MercureHubTest extends TestCase
+{
+    private HubInterface $hub;
+    private SerializerInterface $serializer;
+    private EncoderInterface $encoder;
+    private IriConverterInterface $iriConverter;
+
+    public function setUp(): void {
+        $this->hub = $this->getMockBuilder(HubInterface::class)->disableOriginalConstructor()->getMock();
+        $this->serializer = $this->getMockBuilder(SerializerInterface::class)->disableOriginalConstructor()->getMock();
+        $this->encoder = $this->getMockBuilder(EncoderInterface::class)->disableOriginalConstructor()->getMock();
+        $this->iriConverter = $this->getMockBuilder(IriConverterInterface::class)->disableOriginalConstructor()->getMock();
+    }
+
+    public function testCreateUpdate(): void {
+        $mercureHub = $this
+            ->getMockBuilder(TestableMercureHub::class)
+            ->setConstructorArgs([$this->hub, $this->serializer, $this->encoder, $this->iriConverter])
+            ->setMethodsExcept(['createUpdate'])
+            ->getMock();
+
+        $update = $mercureHub->createUpdate(1, "{'foo': 1}");
+
+        $this->assertEquals(['access/1'], $update->getTopics());
+        $this->assertEquals("{'foo': 1}", $update->getData());
+        $this->assertEquals(true, $update->isPrivate());
+    }
+
+    public function testPublish(): void
+    {
+        $mercureHub = $this
+            ->getMockBuilder(TestableMercureHub::class)
+            ->setConstructorArgs([$this->hub, $this->serializer, $this->encoder, $this->iriConverter])
+            ->setMethodsExcept(['publish'])
+            ->getMock();
+
+        $entity = $this->getMockBuilder(Entity::class)->disableOriginalConstructor()->getMock();
+
+        $this->iriConverter->expects(self::once())->method('getIriFromItem')->with($entity)->willReturn('/api/entity/1');
+        $this->serializer->expects(self::once())->method('serialize')->with($entity, 'jsonld', [])->willReturn("{'foo': 1}");
+
+        $this->encoder
+            ->expects(self::once())
+            ->method('encode')
+            ->with([
+                'iri' => '/api/entity/1',
+                'operation' => 'update',
+                'data' => "{'foo': 1}"
+            ], 'jsonld')
+            ->willReturn("{'iri':'/api/entity/1','operation':'update','data':'{\'foo\':1}'");
+
+        $update = new Update(
+            'access/1',
+            "{'iri':'/api/entity/1','operation':'update','data':'{\'foo\':1}'",
+            true
+        );
+
+        $mercureHub
+            ->expects(self::once())
+            ->method('createUpdate')
+            ->with(1, "{'iri':'/api/entity/1','operation':'update','data':'{\'foo\':1}'")
+            ->willReturn($update);
+
+        $this->hub->expects(self::once())->method('publish')->with($update);
+
+        $mercureHub->publish(1, $entity);
+    }
+
+    public function testPublishInvalidOperation(): void
+    {
+        $mercureHub = $this
+            ->getMockBuilder(TestableMercureHub::class)
+            ->setConstructorArgs([$this->hub, $this->serializer, $this->encoder, $this->iriConverter])
+            ->setMethodsExcept(['publish'])
+            ->getMock();
+
+        $entity = $this->getMockBuilder(Entity::class)->disableOriginalConstructor()->getMock();
+
+        $this->expectException(\InvalidArgumentException::class);
+        $mercureHub->publish(1, $entity, 'foo');
+    }
+
+    public function testPublishUpdate(): void {
+        $mercureHub = $this
+            ->getMockBuilder(TestableMercureHub::class)
+            ->setConstructorArgs([$this->hub, $this->serializer, $this->encoder, $this->iriConverter])
+            ->setMethodsExcept(['publishUpdate'])
+            ->getMock();
+
+        $entity = $this->getMockBuilder(Entity::class)->disableOriginalConstructor()->getMock();
+
+        $mercureHub->expects(self::once())->method('publish')->with(1, $entity, 'update');
+        $mercureHub->publishUpdate(1, $entity);
+    }
+
+    public function testPublishCreate(): void {
+        $mercureHub = $this
+            ->getMockBuilder(TestableMercureHub::class)
+            ->setConstructorArgs([$this->hub, $this->serializer, $this->encoder, $this->iriConverter])
+            ->setMethodsExcept(['publishCreate'])
+            ->getMock();
+
+        $entity = $this->getMockBuilder(Entity::class)->disableOriginalConstructor()->getMock();
+
+        $mercureHub->expects(self::once())->method('publish')->with(1, $entity, 'create');
+
+        $mercureHub->publishCreate(1, $entity);
+    }
+
+    public function testPublishDelete(): void {
+        $mercureHub = $this
+            ->getMockBuilder(TestableMercureHub::class)
+            ->setConstructorArgs([$this->hub, $this->serializer, $this->encoder, $this->iriConverter])
+            ->setMethodsExcept(['publishDelete'])
+            ->getMock();
+
+        $entity = $this->getMockBuilder(Entity::class)->disableOriginalConstructor()->getMock();
+
+        $mercureHub->expects(self::once())->method('publish')->with(1, $entity, 'delete');
+
+        $mercureHub->publishDelete(1, $entity);
+    }
+}

+ 157 - 0
tests/Service/NotifierTest.php

@@ -0,0 +1,157 @@
+<?php
+
+namespace App\Tests\Service;
+
+use App\Entity\Access\Access;
+use App\Entity\Core\File;
+use App\Entity\Core\Notification;
+use App\Entity\Organization\Organization;
+use App\Enum\Core\NotificationTypeEnum;
+use App\Service\MercureHub;
+use App\Service\Notifier;
+use Doctrine\ORM\EntityManagerInterface;
+use PHPUnit\Framework\TestCase;
+
+class TestableNotifier extends Notifier {
+    public function createNotification(Access $access, string $name, string $type, array $message, string $link = null): Notification {
+        return parent::createNotification($access, $name, $type, $message, $link);
+    }
+}
+
+class NotifierTest extends TestCase
+{
+    private EntityManagerInterface $em;
+    private MercureHub $mercureHub;
+
+    public function setUp(): void {
+        $this->em = $this->getMockBuilder(EntityManagerInterface::class)->disableOriginalConstructor()->getMock();
+        $this->mercureHub = $this->getMockBuilder(MercureHub::class)->disableOriginalConstructor()->getMock();
+    }
+
+    public function testCreateNotification(): void {
+        $notifier = $this
+            ->getMockBuilder(TestableNotifier::class)
+            ->setConstructorArgs([$this->em, $this->mercureHub])
+            ->setMethodsExcept(['createNotification'])
+            ->getMock();
+
+        $organization = $this->getMockBuilder(Organization::class)->getMock();
+        $access = $this->getMockBuilder(Access::class)->getMock();
+        $access->method('getId')->willReturn(1);
+        $access->method('getOrganization')->willReturn($organization);
+
+        $notification = $notifier->createNotification(
+            $access,
+            'test',
+            NotificationTypeEnum::MESSAGE()->getValue(),
+            ['message'],
+            'link'
+        );
+
+        $this->assertEquals('test', $notification->getName());
+        $this->assertEquals($access, $notification->getRecipientAccess());
+        $this->assertEquals($organization, $notification->getRecipientOrganization());
+        $this->assertEquals(NotificationTypeEnum::MESSAGE()->getValue(), $notification->getType());
+        $this->assertEquals(['message'], $notification->getMessage());
+        $this->assertEquals('link', $notification->getLink());
+        $this->assertInstanceOf(\DateTime::class, $notification->getCreateDate());
+        $this->assertInstanceOf(\DateTime::class, $notification->getUpdateDate());
+    }
+
+    public function testNotify(): void {
+        $notifier = $this
+            ->getMockBuilder(TestableNotifier::class)
+            ->setConstructorArgs([$this->em, $this->mercureHub])
+            ->setMethodsExcept(['notify'])
+            ->getMock();
+
+        $notification = $this->getMockBuilder(Notification::class)->getMock();
+        $access = $this->getMockBuilder(Access::class)->getMock();
+        $access->method('getId')->willReturn(1);
+
+        $notifier
+            ->expects(self::once())
+            ->method('createNotification')
+            ->with($access, 'test', NotificationTypeEnum::MESSAGE()->getValue(), ['message'], null)
+            ->willReturn($notification);
+
+        $this->em->expects(self::once())->method('persist')->with($notification);
+        $this->em->expects(self::once())->method('flush');
+        $this->mercureHub->expects(self::once())->method('publishCreate')->with(1, $notification);
+
+        $returned = $notifier->notify($access, 'test', NotificationTypeEnum::MESSAGE()->getValue(), ['message']);
+
+        $this->assertEquals($notification, $returned);
+    }
+
+    public function testNotifyExport(): void {
+        $notifier = $this
+            ->getMockBuilder(TestableNotifier::class)
+            ->setConstructorArgs([$this->em, $this->mercureHub])
+            ->setMethodsExcept(['notifyExport'])
+            ->getMock();
+
+        $access = $this->getMockBuilder(Access::class)->getMock();
+        $file = $this->getMockBuilder(File::class)->getMock();
+        $file->method('getId')->willReturn(1);
+        $file->method('getName')->willReturn('foo.txt');
+
+        $notifier
+            ->expects(self::once())
+            ->method('notify')
+            ->with($access, 'export', NotificationTypeEnum::FILE()->getValue(), ['fileName' => 'foo.txt'], '/api/files/1/download');
+
+        $notifier->notifyExport($access, $file);
+    }
+
+    public function testNotifyMessage(): void {
+        $notifier = $this
+            ->getMockBuilder(TestableNotifier::class)
+            ->setConstructorArgs([$this->em, $this->mercureHub])
+            ->setMethodsExcept(['notifyMessage'])
+            ->getMock();
+
+        $access = $this->getMockBuilder(Access::class)->getMock();
+
+        $notifier
+            ->expects(self::once())
+            ->method('notify')
+            ->with($access, 'message', NotificationTypeEnum::MESSAGE()->getValue(), ['a message']);
+
+        $notifier->notifyMessage($access, ['a message']);
+    }
+
+    public function testNotifySystem(): void {
+        $notifier = $this
+            ->getMockBuilder(TestableNotifier::class)
+            ->setConstructorArgs([$this->em, $this->mercureHub])
+            ->setMethodsExcept(['notifySystem'])
+            ->getMock();
+
+        $access = $this->getMockBuilder(Access::class)->getMock();
+
+        $notifier
+            ->expects(self::once())
+            ->method('notify')
+            ->with($access, 'message', NotificationTypeEnum::SYSTEM()->getValue(), ['a message']);
+
+        $notifier->notifySystem($access, ['a message']);
+    }
+
+    public function testNotifyError(): void {
+        $notifier = $this
+            ->getMockBuilder(TestableNotifier::class)
+            ->setConstructorArgs([$this->em, $this->mercureHub])
+            ->setMethodsExcept(['notifyError'])
+            ->getMock();
+
+        $access = $this->getMockBuilder(Access::class)->getMock();
+
+        $notifier
+            ->expects(self::once())
+            ->method('notify')
+            ->with($access, 'test', NotificationTypeEnum::ERROR()->getValue(), ['a message']);
+
+        $notifier->notifyError($access, 'test', ['a message']);
+    }
+}

+ 0 - 21
tests/Service/ServiceIterator/CurrentAccessExtensionIteratorTest.php

@@ -31,25 +31,4 @@ class CurrentAccessExtensionIteratorTest extends TestCase
 
         $this->assertEquals(true, $actualExt);
     }
-
-    public function testAddWhereError() {
-        $queryBuilder = $this->getMockBuilder(QueryBuilder::class)
-            ->disableOriginalConstructor()
-            ->getMock();
-
-        $mocker = $this->getMockBuilder(AccessExtensionInterface::class);
-
-        $ext1 = $mocker->getMock();
-        $ext1->method('support')->willReturn(false);
-
-        $ext2 = $mocker->getMock();
-        $ext2->method('support')->willReturn(false);
-
-        $extensions = [$ext1, $ext2];
-
-        $iterator = new CurrentAccessExtensionIterator($extensions);
-
-        $this->expectException(Exception::class);
-        $iterator->addWhere($queryBuilder, 'foo');
-    }
 }