Quellcode durchsuchen

complete unit tests

Olivier Massot vor 1 Jahr
Ursprung
Commit
725fc96c16

+ 11 - 8
src/Service/Organization/OrganizationFactory.php

@@ -51,6 +51,8 @@ class OrganizationFactory
 {
     private LoggerInterface $logger;
 
+    protected PhoneNumberUtil $phoneNumberUtil;
+
     public function __construct(
         private readonly SubdomainService                     $subdomainService,
         private readonly OrganizationRepository               $organizationRepository,
@@ -63,7 +65,9 @@ class OrganizationFactory
         private readonly BindFileService                      $bindFileService,
         private readonly OrganizationIdentificationRepository $organizationIdentificationRepository,
         private readonly ApiLegacyRequestService              $apiLegacyRequestService
-    ) {}
+    ) {
+        $this->phoneNumberUtil = PhoneNumberUtil::getInstance();
+    }
 
     #[Required]
     /** @see https://symfony.com/doc/current/logging/channels_handlers.html#how-to-autowire-logger-channels */
@@ -464,11 +468,10 @@ class OrganizationFactory
      */
     protected function makeContactPoint(OrganizationCreationRequest $organizationCreationRequest): ContactPoint
     {
-        $phoneUtil = PhoneNumberUtil::getInstance();
-        if (!$phoneUtil->isPossibleNumber($organizationCreationRequest->getPhoneNumber())) {
+        if (!$this->phoneNumberUtil->isPossibleNumber($organizationCreationRequest->getPhoneNumber())) {
             throw new \RuntimeException("Phone number is invalid or missing");
         }
-        $phoneNumber = $phoneUtil->parse($organizationCreationRequest->getPhoneNumber());
+        $phoneNumber = $this->phoneNumberUtil->parse($organizationCreationRequest->getPhoneNumber());
 
         $contactPoint = new ContactPoint();
         $contactPoint->setContactType(ContactPointTypeEnum::PRINCIPAL);
@@ -741,9 +744,9 @@ class OrganizationFactory
      */
     protected function normalizeIdentificationField(string $value): string {
         $value = strtolower(trim($value));
-        $value = preg_replace('/[éèê]/', 'e', $value);
-        $value = preg_replace('/[à]/', 'a', $value);
-        $value = preg_replace('/[ç]/', 'c', $value);
-        return preg_replace('/[^a-z0-9]+/', '+', $value);
+        $value = preg_replace('/[éèê]/u', 'e', $value);
+        $value = preg_replace('/[à]/u', 'a', $value);
+        $value = preg_replace('/[ç]/u', 'c', $value);
+        return preg_replace('/[^a-z0-9]+/u', '+', $value);
     }
 }

+ 208 - 14
tests/Unit/Service/Organization/OrganizationFactoryTest.php

@@ -41,6 +41,8 @@ use App\Service\Typo3\SubdomainService;
 use App\Service\Typo3\Typo3Service;
 use App\Service\Utils\DatesUtils;
 use Doctrine\ORM\EntityManagerInterface;
+use libphonenumber\PhoneNumber;
+use libphonenumber\PhoneNumberUtil;
 use PHPUnit\Framework\MockObject\MockObject;
 use PHPUnit\Framework\TestCase;
 use Psr\Log\LoggerInterface;
@@ -48,6 +50,11 @@ use Symfony\Component\HttpFoundation\Response;
 use Symfony\Contracts\HttpClient\ResponseInterface;
 
 class TestableOrganizationFactory extends OrganizationFactory {
+    public function setPhoneNumberUtil(PhoneNumberUtil $phoneNumberUtil): void
+    {
+        $this->phoneNumberUtil = $phoneNumberUtil;
+    }
+
     public function interruptIfOrganizationExists(OrganizationCreationRequest $organizationCreationRequest): void
     {
         parent::interruptIfOrganizationExists($organizationCreationRequest);
@@ -141,6 +148,7 @@ class OrganizationFactoryTest extends TestCase
     private readonly MockObject | LoggerInterface                             $logger;
     private readonly MockObject | OrganizationIdentificationRepository        $organizationIdentificationRepository;
     private readonly MockObject | ApiLegacyRequestService                     $apiLegacyRequestService;
+    private readonly MockObject | PhoneNumberUtil                             $phoneNumberUtil;
 
     public function setUp(): void
     {
@@ -156,6 +164,7 @@ class OrganizationFactoryTest extends TestCase
         $this->logger = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock();
         $this->organizationIdentificationRepository = $this->getMockBuilder(OrganizationIdentificationRepository::class)->disableOriginalConstructor()->getMock();
         $this->apiLegacyRequestService = $this->getMockBuilder(ApiLegacyRequestService::class)->disableOriginalConstructor()->getMock();
+        $this->phoneNumberUtil = $this->getMockBuilder(PhoneNumberUtil::class)->disableOriginalConstructor()->getMock();
     }
 
     public function tearDown(): void
@@ -181,11 +190,11 @@ class OrganizationFactoryTest extends TestCase
                     $this->organizationIdentificationRepository,
                     $this->apiLegacyRequestService
                 ])
-            ->setMethodsExcept(['setLoggerInterface', $methodName])
+            ->setMethodsExcept(['setLoggerInterface', 'setPhoneNumberUtil', $methodName])
             ->getMock();
 
         $organizationFactory->setLoggerInterface($this->logger);
-
+        $organizationFactory->setPhoneNumberUtil($this->phoneNumberUtil);
         return $organizationFactory;
     }
 
@@ -244,6 +253,11 @@ class OrganizationFactoryTest extends TestCase
                 ["Adminassos db updated"]
             );
 
+        $organizationCreationRequest
+            ->expects(self::once())
+            ->method('setStatus')
+            ->with(OrganizationCreationRequest::STATUS_OK);
+
         $result = $organizationFactory->create($organizationCreationRequest);
 
         $this->assertEquals(
@@ -398,6 +412,72 @@ class OrganizationFactoryTest extends TestCase
         );
     }
 
+    public function testCreateWithErrors(): void {
+        $organizationFactory = $this->getOrganizationFactoryMockFor('create');
+
+        $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
+        $organizationCreationRequest->method('getName')->willReturn('foo');
+        $organizationCreationRequest->method('getSubdomain')->willReturn('subdomain');
+        $organizationCreationRequest->method('isClient')->willReturn(true);
+        $organizationCreationRequest->method('getCreateWebsite')->willReturn(true);
+
+        $organizationFactory->expects(self::once())->method('interruptIfOrganizationExists');
+
+        $organization = $this->getMockBuilder(Organization::class)->getMock();
+        $organizationFactory
+            ->expects(self::once())
+            ->method('makeOrganizationWithRelations')
+            ->with($organizationCreationRequest)
+            ->willReturn($organization);
+
+        $this->dolibarrApiService
+            ->method('createSociety')
+            ->with($organization, true)
+            ->willThrowException(new \RuntimeException('An error happened'));
+
+        $this->bindFileService
+            ->method('registerSubdomain')
+            ->with('subdomain')
+            ->willThrowException(new \RuntimeException('An error happened'));
+
+        $organizationFactory
+            ->method('createTypo3Website')
+            ->with($organization)
+            ->willThrowException(new \RuntimeException('An error happened'));
+
+        $organizationFactory
+            ->method('updateAdminassosDb')
+            ->with($organization)
+            ->willThrowException(new \RuntimeException('An error happened'));
+
+        $this->logger
+            ->expects(self::exactly(4))
+            ->method('critical')
+            ->willReturnOnConsecutiveCalls([
+                'An error happened while creating the dolibarr society, please proceed manually.',
+                'An error happened while updating the bind file, please proceed manually.',
+                'An error happened while creating the typo3 website, please proceed manually.',
+                'An error happened while updating the adminassos db, please proceed manually.',
+            ]);
+
+        $this->logger
+            ->expects(self::once())
+            ->method('warning')
+            ->with("-- Operation ended with errors, check the logs for more information --");
+
+        $organizationCreationRequest
+            ->expects(self::once())
+            ->method('setStatus')
+            ->with(OrganizationCreationRequest::STATUS_OK_WITH_ERRORS);
+
+        $result = $organizationFactory->create($organizationCreationRequest);
+
+        $this->assertEquals(
+            $organization,
+            $result
+        );
+    }
+
     public function testInterruptIfOrganizationExistsNotExisting(): void
     {
         $organizationFactory = $this->getOrganizationFactoryMockFor('interruptIfOrganizationExists');
@@ -982,6 +1062,22 @@ class OrganizationFactoryTest extends TestCase
         );
     }
 
+    public function testMakePostalAddressUnexistingCountry(): void
+    {
+        $organizationFactory = $this->getOrganizationFactoryMockFor('makePostalAddress');
+
+        $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
+        $organizationCreationRequest->method('getCountryId')->willReturn(1);
+
+        $this->countryRepository->expects(self::once())->method('find')->with(1)->willReturn(null);
+
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionMessage('No country found for id 1');
+
+        $organizationFactory->makePostalAddress($organizationCreationRequest);
+
+    }
+
     public function testMakeContactPoint(): void
     {
         $organizationFactory = $this->getOrganizationFactoryMockFor('makeContactPoint');
@@ -991,6 +1087,19 @@ class OrganizationFactoryTest extends TestCase
         $organizationCreationRequest->method('getPhoneNumber')->willReturn('+33102030405');
         $organizationCreationRequest->method('getEmail')->willReturn('contact@domain.net');
 
+        $this->phoneNumberUtil
+            ->method('isPossibleNumber')
+            ->with('+33102030405')
+            ->willReturn(true);
+
+        $phoneNumber = $this->getMockBuilder(PhoneNumber::class)->getMock();
+
+        $this->phoneNumberUtil
+            ->expects(self::once())
+            ->method('parse')
+            ->with('+33102030405')
+            ->willReturn($phoneNumber);
+
         $contactPoint = $organizationFactory->makeContactPoint($organizationCreationRequest);
 
         $this->assertEquals(
@@ -999,14 +1108,35 @@ class OrganizationFactoryTest extends TestCase
         );
 
         $this->assertEquals(
-            '33',
-            $contactPoint->getTelphone()->getCountryCode()
+            $phoneNumber,
+            $contactPoint->getTelphone()
         );
+    }
 
-        $this->assertEquals(
-            '102030405',
-            $contactPoint->getTelphone()->getNationalNumber()
-        );
+    public function testMakeContactPointInvalidPhoneNumber(): void
+    {
+        $organizationFactory = $this->getOrganizationFactoryMockFor('makeContactPoint');
+
+        $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
+
+        $organizationCreationRequest->method('getPhoneNumber')->willReturn('invalid');
+        $organizationCreationRequest->method('getEmail')->willReturn('contact@domain.net');
+
+        $this->phoneNumberUtil
+            ->method('isPossibleNumber')
+            ->with('invalid')
+            ->willReturn(false);
+
+        $phoneNumber = $this->getMockBuilder(PhoneNumber::class)->getMock();
+
+        $this->phoneNumberUtil
+            ->expects(self::never())
+            ->method('parse');
+
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionMessage('Phone number is invalid or missing');
+
+        $organizationFactory->makeContactPoint($organizationCreationRequest);
     }
 
     public function testMakeNetworkOrganization(): void {
@@ -1064,6 +1194,27 @@ class OrganizationFactoryTest extends TestCase
         $organizationFactory->makeNetworkOrganization($organizationCreationRequest);
     }
 
+
+    public function testMakeNetworkOrganizationParentIsNotManager(): void {
+        $organizationFactory = $this->getOrganizationFactoryMockFor('makeNetworkOrganization');
+
+        DatesUtils::setFakeDatetime('2024-01-01');
+
+        $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
+        $organizationCreationRequest->method('getParentId')->willReturn(123);
+
+        $parent = $this->getMockBuilder(Organization::class)->getMock();
+        $settings = $this->getMockBuilder(Settings::class)->getMock();
+        $settings->method('getProduct')->willReturn(SettingsProductEnum::SCHOOL);
+        $parent->method('getSettings')->willReturn($settings);
+        $this->organizationRepository->expects(self::once())->method('find')->with(123)->willReturn($parent);
+
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionMessage("Parent organization must have the product 'manager' (actual product: 'school')");
+
+        $organizationFactory->makeNetworkOrganization($organizationCreationRequest);
+    }
+
     public function testMakeNetworkOrganizationMissingNetwork(): void {
         $organizationFactory = $this->getOrganizationFactoryMockFor('makeNetworkOrganization');
 
@@ -1076,12 +1227,6 @@ class OrganizationFactoryTest extends TestCase
         $parent->method('getSettings')->willReturn($settings);
         $this->organizationRepository->expects(self::once())->method('find')->with(123)->willReturn($parent);
 
-        $this->organizationUtils
-            ->expects(self::once())
-            ->method('getActiveNetworkOrganization')
-            ->with($parent)
-            ->willReturn(null);
-
         $this->expectException(\RuntimeException::class);
         $this->expectExceptionMessage('No network found for parent 123');
 
@@ -1468,4 +1613,53 @@ class OrganizationFactoryTest extends TestCase
         $this->assertNull($result);
     }
 
+    public function testUpdateAdminassosDb(): void {
+        $organizationFactory = $this->getOrganizationFactoryMockFor('updateAdminassosDb');
+
+        $response = $this->getMockBuilder(ResponseInterface::class)->disableOriginalConstructor()->getMock();
+        $response->method('getStatusCode')->willReturn(Response::HTTP_OK);
+
+        $this->apiLegacyRequestService
+            ->expects(self::once())
+            ->method('post')
+            ->with('/_internal/secure/organization/creation-event', [ 'organizationId' => 123 ])
+            ->willReturn($response);
+
+        $organization = $this->getMockBuilder(Organization::class)->getMock();
+        $organization->method('getId')->willReturn(123);
+
+        $organizationFactory->updateAdminassosDb($organization);
+    }
+
+    public function testUpdateAdminassosDbError(): void {
+        $organizationFactory = $this->getOrganizationFactoryMockFor('updateAdminassosDb');
+
+        $response = $this->getMockBuilder(ResponseInterface::class)->disableOriginalConstructor()->getMock();
+        $response->method('getStatusCode')->willReturn(Response::HTTP_BAD_REQUEST);
+        $response->method('getContent')->willReturn('some error');
+
+        $this->apiLegacyRequestService
+            ->expects(self::once())
+            ->method('post')
+            ->with('/_internal/secure/organization/creation-event', [ 'organizationId' => 123 ])
+            ->willReturn($response);
+
+        $organization = $this->getMockBuilder(Organization::class)->getMock();
+        $organization->method('getId')->willReturn(123);
+
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionMessage('An error happened while updating the adminassos database: some error');
+
+        $organizationFactory->updateAdminassosDb($organization);
+    }
+
+    public function testNormalizeIdentificationField(): void {
+        $organizationFactory = $this->getOrganizationFactoryMockFor('normalizeIdentificationField');
+
+        $this->assertEquals(
+            'c+est+une+phrase+normalisee+',
+            $organizationFactory->normalizeIdentificationField("C'est une phrase normalisée.")
+        );
+    }
+
 }