organizationRepository = $this->getMockBuilder(OrganizationRepository::class) ->disableOriginalConstructor() ->getMock(); $this->accessRepository = $this->getMockBuilder(AccessRepository::class) ->disableOriginalConstructor() ->getMock(); $this->functionTypeRepository = $this->getMockBuilder(FunctionTypeRepository::class) ->disableOriginalConstructor() ->getMock(); $this->dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class) ->disableOriginalConstructor() ->getMock(); $this->translator = $this->getMockBuilder(TranslatorInterface::class) ->disableOriginalConstructor() ->getMock(); $this->logger = $this->getMockBuilder(LoggerInterface::class) ->disableOriginalConstructor() ->getMock(); $this->logger->method('info')->willReturnSelf(); $this->logger->method('debug')->willReturnSelf(); $this->logger->method('warning')->willReturnSelf(); $this->logger->method('error')->willReturnSelf(); } #[Pure] private function newDolibarrSyncService(): TestableDolibarrSyncService { return new TestableDolibarrSyncService( $this->organizationRepository, $this->accessRepository, $this->functionTypeRepository, $this->dolibarrApiService, $this->translator, $this->logger ); } private function getJsonContentFromFixture(string $filename): array { $filepath = dirname(__FILE__) . '/fixtures/' . $filename; return json_decode(file_get_contents($filepath), true); } public function testScan() { // mock services and special methods from repos $this->dolibarrApiService ->expects($this->once()) ->method('getAllClients') ->willReturn( $this->getJsonContentFromFixture('thirdparty.json') ); $this->dolibarrApiService->method('getSociety')->willReturnMap( [ [12097, ['id' => 711]], [91295, ['id' => 5086]] ] ); $this->accessRepository ->expects($this->once()) ->method('getAllActiveMembersAndMissions') ->willReturn( [ ['id' => 1, 'organization_id' => 37306, 'mission' => FunctionEnum::PRESIDENT()->getValue()], ['id' => 1, 'organization_id' => 37306, 'mission' => FunctionEnum::ADHERENT()->getValue()], ['id' => 2, 'organization_id' => 37306, 'mission' => FunctionEnum::TREASURER()->getValue()], ['id' => 2, 'organization_id' => 37306, 'mission' => FunctionEnum::ADHERENT()->getValue()], ['id' => 3, 'organization_id' => 37306, 'mission' => FunctionEnum::STUDENT()->getValue()], ['id' => 3, 'organization_id' => 37306, 'mission' => FunctionEnum::ADHERENT()->getValue()], ] ); // Function types $functionType1 = $this->getMockBuilder(FunctionType::class)->getMock(); $functionType1->method('getMission')->willReturn(FunctionEnum::DIRECTOR()->getValue()); $functionType2 = $this->getMockBuilder(FunctionType::class)->getMock(); $functionType2->method('getMission')->willReturn(FunctionEnum::PRESIDENT()->getValue()); $this->functionTypeRepository ->expects($this->once()) ->method('findBy') ->with(['roleByDefault' => RoleEnum::ROLE_ADMIN()->getValue()]) ->willReturn([$functionType1, $functionType2]); // Organization's name $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization->method('getId')->willReturn(37306); $organization->method('getName')->willReturn("Etablissement d'Enseignement Artistique"); // Postal address $organizationAddressPostal = $this->getMockBuilder(OrganizationAddressPostal::class)->getMock(); $addressPostal = $this->getMockBuilder(AddressPostal::class)->getMock(); $addressPostal->method('getStreetAddress')->willReturn('21b baker street'); $addressPostal->method('getStreetAddressSecond')->willReturn(''); $addressPostal->method('getStreetAddressThird')->willReturn(''); $addressPostal->method('getAddressOwner')->willReturn(''); $addressPostal->method('getPostalCode')->willReturn('250 329'); $addressPostal->method('getAddressCity')->willReturn('Londres'); $organizationAddressPostal->method('getType')->willReturn(AddressPostalOrganizationTypeEnum::ADDRESS_CONTACT()->getValue()); $organizationAddressPostal->method('getAddressPostal')->willReturn($addressPostal); $organization->method('getOrganizationAddressPostals')->willReturn( new ArrayCollection([$organizationAddressPostal]) ); // Email and phone $phoneUtil = PhoneNumberUtil::getInstance(); $contactPoint = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint->method('getContactType')->willReturn(ContactPointTypeEnum::CONTACT()->getValue()); $contactPoint->method('getEmail')->willReturn('email@email.com'); $phoneNumber = $phoneUtil->parse('01 02 03 04 05', 'FR'); $contactPoint->method('getTelphone')->willReturn($phoneNumber); $organization->method('getContactPoints')->willReturn( new ArrayCollection([$contactPoint]) ); // Network $network = $this->getMockBuilder(Network::class)->getMock(); $network->method('getId')->willReturn(91295); $networkOrganization = $this->getMockBuilder(NetworkOrganization::class)->getMock(); $networkOrganization->method('getNetwork')->willReturn($network); $organization->method('getNetworkOrganizations')->willReturn(new ArrayCollection([$networkOrganization])); // Product $settings = $this->getMockBuilder(Settings::class)->getMock(); $settings->method('getProduct')->willReturn(SettingsProductEnum::SCHOOL()->getValue()); $organization->method('getSettings')->willReturn($settings); // Get dolibarr contacts $this->dolibarrApiService ->method('getContacts') ->with(1726) ->willReturn( array_filter( $this->getJsonContentFromFixture('contacts.json'), static function ($c) { return in_array( (int)$c["array_options"]["options_2iopen_person_id"], [ 108939, // existing person, to be updated 156252 // no matching person, to be deleted // a new contact shall be created too ] ); } ) ); $this->organizationRepository->method('find')->willReturn($organization); $access1 = $this->getMockBuilder(Access::class)->getMock(); $access1->method('getId')->willReturn(1); $person1 = $this->getMockBuilder(Person::class)->getMock(); $person1->method('getId')->willReturn(108939); $person1->method('getName')->willReturn('Holmes'); $person1->method('getGender')->willReturn('MISTER'); $person1->method('getGivenName')->willReturn('Sherlock'); $person1->method('getGivenName')->willReturn('Sherlock'); $personContactPoint1 = $this->getMockBuilder(ContactPoint::class)->getMock(); $personContactPoint1->method('getContactType')->willReturn(ContactPointTypeEnum::CONTACT()->getValue()); $personContactPoint1->method('getEmail')->willReturn('sherlock@holmes.com'); $phoneNumber1 = $phoneUtil->parse('02 98 76 54 32', 'FR'); $personContactPoint1->method('getTelphone')->willReturn($phoneNumber1); $personContactPoint1->method('getMobilPhone')->willReturn(null); $person1->method('getContactPoints')->willReturn( new ArrayCollection([$personContactPoint1]) ); $access1->method('getPerson')->willReturn($person1); $access2 = $this->getMockBuilder(Access::class)->getMock(); $access2->method('getId')->willReturn(1); $person2 = $this->getMockBuilder(Person::class)->getMock(); $person2->method('getId')->willReturn(1000); $person2->method('getName')->willReturn('Watson'); $person2->method('getGender')->willReturn('MISTER'); $person2->method('getGivenName')->willReturn('John'); $person2->method('getGivenName')->willReturn('John'); $personContactPoint2 = $this->getMockBuilder(ContactPoint::class)->getMock(); $personContactPoint2->method('getContactType')->willReturn(ContactPointTypeEnum::CONTACT()->getValue()); $personContactPoint2->method('getEmail')->willReturn('docteur@watson.com'); $phoneNumber2 = $phoneUtil->parse('02 10 11 12 13', 'FR'); $personContactPoint2->method('getTelphone')->willReturn($phoneNumber2); $personContactPoint2->method('getMobilPhone')->willReturn(null); $person2->method('getContactPoints')->willReturn( new ArrayCollection([$personContactPoint2]) ); $access2->method('getPerson')->willReturn($person2); $this->accessRepository->method('find')->willReturnMap( [ [1, null, null, $access1], [2, null, null, $access2], ] ); $this->translator->method('trans')->willReturnMap( [ ['STUDENTS_COUNT', [], null, null, "Nombre d'élèves"], ['ADHERENTS_COUNT', [], null, null, "Nombre d'adhérents"], ['ADMIN_ACCESS_COUNT', [], null, null, "Nombre d'accès admin"], ] ); $syncService = $this->newDolibarrSyncService(); $operations = $syncService->scan(); $this->assertCount(4, $operations); $this->assertEquals( [ '[PUT thirdparties/1726]', "address : `\n217, rue Raoul Follereau\n` => `21b baker street`", 'zip : `74300` => `250 329`', 'town : `CLUSES` => `Londres`', 'email : `` => `email@email.com`', 'phone : `+33678403010` => `+33102030405`', 'parent : `` => `5086`', "array_options.options_2iopeninfoopentalent : `` => `Nombre d'élèves : 1\nNombre d'adhérents : 3\nNombre d'accès admin : 1`" ], $operations[0]->getChangeLog() ); $this->assertEquals( [ '[PUT contacts/5868]', 'civility_code : `MME` => ``', 'lastname : `DUPONT` => `Holmes`', 'firstname : `Valerie` => `Sherlock`', 'email : `abcd@hotmail.com` => ``', 'phone_pro : `+33478570000` => ``', 'phone_mobile : `+33682980000` => ``', 'poste : `Secrétaire` => ``' ], $operations[1]->getChangeLog() ); $this->assertEquals( [ '[POST contacts]', 'civility_code : (new) => ``', 'lastname : (new) => `Watson`', 'firstname : (new) => `John`', 'email : (new) => ``', 'phone_pro : (new) => ``', 'phone_mobile : (new) => ``', 'poste : (new) => ``', 'statut : (new) => `1`', 'array_options.options_2iopen_person_id : (new) => `1000`', 'socid : (new) => `1726`' ], $operations[2]->getChangeLog() ); $this->assertEquals( ['[PUT contacts/5869]', 'statut : `1` => `0`'], $operations[3]->getChangeLog() ); } public function testExecuteError() { $operation = new CreateOperation('operation 1', 'thirdparty', ['data' => 1]); $this->assertEquals($operation->getStatus(), $operation::STATUS_READY); $responseError = $this->getMockBuilder(ResponseInterface::class)->getMock(); $responseError->method('getStatusCode')->willReturn(500); $this->dolibarrApiService->method('request')->willReturn($responseError); // POST operation will returned a server error $syncService = $this->newDolibarrSyncService(); $operation = $syncService->execute([$operation])[0]; $this->assertEquals($operation::STATUS_ERROR, $operation->getStatus()); } public function testExecuteInvalid() { $operation = new UpdateOperation('operation 1', 'thirdparty', 1, ['data' => 1]); $responseInvalid = $this->getMockBuilder(ResponseInterface::class)->getMock(); $responseInvalid->method('getStatusCode')->willReturn(200); $responseInvalid->method('toArray')->willReturn(['data' => 0]); $this->dolibarrApiService->method('request')->willReturn($responseInvalid); // POST operation will return a different content that the one which were posted, this should log a warning $this->logger->expects($this->once())->method('warning'); $syncService = $this->newDolibarrSyncService(); $operation = $syncService->execute([$operation])[0]; $this->assertEquals($operation::STATUS_DONE, $operation->getStatus()); } public function testExecuteOk() { $operation = new CreateOperation('operation 1', 'thirdparty', ['data' => 1]); $responseOk = $this->getMockBuilder(ResponseInterface::class)->getMock(); $responseOk->method('getStatusCode')->willReturn(200); $responseOk->method('toArray')->willReturn(['data' => 1]); $this->dolibarrApiService->method('request')->willReturn($responseOk); $syncService = $this->newDolibarrSyncService(); $operation = $syncService->execute([$operation])[0]; $this->assertEquals($operation::STATUS_DONE, $operation->getStatus()); } public function testGetDolibarrSocietiesIndex() { $this->dolibarrApiService ->expects($this->once()) ->method('getAllClients') ->willReturn( $this->getJsonContentFromFixture('thirdparties.json') ); $syncService = $this->newDolibarrSyncService(); $index = $syncService->getDolibarrSocietiesIndex(); $this->assertEquals("13930", $index[13930]['array_options']['options_2iopen_organization_id']); } public function testFindDolibarrContactFor() { $contacts = $this->getJsonContentFromFixture('contacts.json'); // Find by id $person1 = $this->getMockBuilder(Person::class)->getMock(); $person1->method('getId')->willReturn(108939); $contact1 = TestableDolibarrSyncService::findDolibarrContactFor($contacts, $person1); $this->assertEquals("5868", $contact1['id']); // Find by full name (contact already has another person id, it should not be returned) $person2 = $this->getMockBuilder(Person::class)->getMock(); $person2->method('getId')->willReturn(-1); $person2->method('getName')->willReturn('dupont'); $person2->method('getGivenName')->willReturn('Valerie'); $contact2 = TestableDolibarrSyncService::findDolibarrContactFor($contacts, $person2); $this->assertEquals(null, $contact2); // Find by full name (contact has no person id, it should be returned) $person3 = $this->getMockBuilder(Person::class)->getMock(); $person3->method('getId')->willReturn(-1); $person3->method('getName')->willReturn('ZORRO'); $person3->method('getGivenName')->willReturn('Fabrice'); $contact3 = TestableDolibarrSyncService::findDolibarrContactFor($contacts, $person3); $this->assertEquals("5872", $contact3['id']); // Do not find $person4 = $this->getMockBuilder(Person::class)->getMock(); $person4->method('getId')->willReturn(-1); $contact4 = TestableDolibarrSyncService::findDolibarrContactFor($contacts, $person4); $this->assertEquals(null, $contact4); } public function testActiveMembersIndex() { $this->accessRepository ->expects($this->once()) ->method('getAllActiveMembersAndMissions') ->willReturn( [ ['id' => 123, 'organization_id' => 1, 'mission' => FunctionEnum::PRESIDENT()->getValue()], ['id' => 123, 'organization_id' => 1, 'mission' => FunctionEnum::TEACHER()->getValue()], ['id' => 124, 'organization_id' => 1, 'mission' => FunctionEnum::ADMINISTRATIVE_STAFF()->getValue()], ['id' => 125, 'organization_id' => 2, 'mission' => FunctionEnum::ADHERENT()->getValue()], ] ); $syncService = $this->newDolibarrSyncService(); $this->assertEquals( [ 1 => [ 123 => [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::TEACHER()->getValue()], 124 => [FunctionEnum::ADMINISTRATIVE_STAFF()->getValue()] ], 2 => [ 125 => [FunctionEnum::ADHERENT()->getValue()] ] ], $syncService->getActiveMembersIndex() ); } public function testSanitizeDolibarrData() { $this->assertEquals(null, TestableDolibarrSyncService::sanitizeDolibarrData(null)); $this->assertEquals( ['a' => 'A', 'b' => null, 'c' => ['d' => 'D', 'e' => null]], TestableDolibarrSyncService::sanitizeDolibarrData( ['a' => 'A', 'b' => '', 'c' => ['d' => 'D', 'e' => '']] ) ); } public function testGetOrganizationPostalAddress() { $organization = $this->getMockBuilder(Organization::class)->getMock(); $organizationAddressPostal1 = $this->getMockBuilder(OrganizationAddressPostal::class)->getMock(); $organizationAddressPostal2 = $this->getMockBuilder(OrganizationAddressPostal::class)->getMock(); $organizationAddressPostal3 = $this->getMockBuilder(OrganizationAddressPostal::class)->getMock(); $addressPostal = $this->getMockBuilder(AddressPostal::class)->getMock(); $organizationAddressPostal1->method('getType')->willReturn(AddressPostalOrganizationTypeEnum::ADDRESS_PRACTICE()->getValue()); $organizationAddressPostal2->method('getType')->willReturn(AddressPostalOrganizationTypeEnum::ADDRESS_BILL()->getValue()); $organizationAddressPostal3->method('getType')->willReturn(AddressPostalOrganizationTypeEnum::ADDRESS_OTHER()->getValue()); $organizationAddressPostal2->method('getAddressPostal')->willReturn($addressPostal); $organization->expects($this->once()) ->method('getOrganizationAddressPostals') ->willReturn( new ArrayCollection([$organizationAddressPostal1, $organizationAddressPostal2, $organizationAddressPostal3]) ); $syncService = $this->newDolibarrSyncService($organization); $this->assertEquals( $addressPostal, $syncService->getOrganizationPostalAddress($organization) ); $organization2 = $this->getMockBuilder(Organization::class)->getMock(); $organization2->expects($this->once()) ->method('getOrganizationAddressPostals') ->willReturn(new ArrayCollection([])); $this->assertEquals( null, $syncService->getOrganizationPostalAddress($organization2) ); } public function testGetOrganizationPhoneWithExistingPhone() { $organization = $this->getMockBuilder(Organization::class)->getMock(); $contactPoint1 = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint2 = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint3 = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint1->method('getContactType')->willReturn(ContactPointTypeEnum::OTHER()->getValue()); $contactPoint2->method('getContactType')->willReturn(ContactPointTypeEnum::BILL()->getValue()); $contactPoint3->method('getContactType')->willReturn(ContactPointTypeEnum::PRINCIPAL()->getValue()); $phoneUtil = PhoneNumberUtil::getInstance(); $phoneNumber = $phoneUtil->parse('0161626365', "FR"); $contactPoint2->method('getTelphone')->willReturn($phoneNumber); $organization ->expects($this->once()) ->method('getContactPoints') ->willReturn( new ArrayCollection([$contactPoint1, $contactPoint2, $contactPoint3]) ); $syncService = $this->newDolibarrSyncService(); $this->assertEquals( '+33161626365', $syncService->getOrganizationPhone($organization) ); } public function testGetOrganizationPhoneWithMobilePhone() { $organization = $this->getMockBuilder(Organization::class)->getMock(); $contactPoint1 = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint2 = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint3 = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint1->method('getContactType')->willReturn(ContactPointTypeEnum::OTHER()->getValue()); $contactPoint2->method('getContactType')->willReturn(ContactPointTypeEnum::BILL()->getValue()); $contactPoint3->method('getContactType')->willReturn(ContactPointTypeEnum::PRINCIPAL()->getValue()); $contactPoint2->expects($this->once())->method('getTelphone')->willReturn(null); $phoneUtil = PhoneNumberUtil::getInstance(); $phoneNumber = $phoneUtil->parse('0661626365', "FR"); $contactPoint2->method('getMobilPhone')->willReturn($phoneNumber); $organization ->expects($this->once()) ->method('getContactPoints') ->willReturn( new ArrayCollection([$contactPoint1, $contactPoint2, $contactPoint3]) ); $syncService = $this->newDolibarrSyncService(); $this->assertEquals( '+33661626365', $syncService->getOrganizationPhone($organization) ); } public function testGetOrganizationPhoneWithNoPhone() { $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization ->expects($this->once()) ->method('getContactPoints') ->willReturn(new ArrayCollection([])); $syncService = $this->newDolibarrSyncService(); $this->assertEquals( null, $syncService->getOrganizationPhone($organization) ); } public function testGetOrganizationEmailWithExistingEmail() { $organization = $this->getMockBuilder(Organization::class)->getMock(); $contactPoint1 = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint2 = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint3 = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint1->method('getContactType')->willReturn(ContactPointTypeEnum::OTHER()->getValue()); $contactPoint2->method('getContactType')->willReturn(ContactPointTypeEnum::BILL()->getValue()); $contactPoint3->method('getContactType')->willReturn(ContactPointTypeEnum::PRINCIPAL()->getValue()); $contactPoint2->method('getEmail')->willReturn('email@email.com'); $organization ->expects($this->once()) ->method('getContactPoints') ->willReturn( new ArrayCollection([$contactPoint1, $contactPoint2, $contactPoint3]) ); $syncService = $this->newDolibarrSyncService(); $this->assertEquals( 'email@email.com', $syncService->getOrganizationEmail($organization) ); } public function testGetOrganizationEmailWithNoEmail() { $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization ->expects($this->once()) ->method('getContactPoints') ->willReturn(new ArrayCollection([])); $syncService = $this->newDolibarrSyncService(); $this->assertEquals( null, $syncService->getOrganizationEmail($organization) ); } public function testCountWithMission() { $members = [ 123 => [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::TEACHER()->getValue()], 124 => [FunctionEnum::TEACHER()->getValue()], 125 => [FunctionEnum::STUDENT()->getValue()], 126 => [FunctionEnum::TREASURER()->getValue()], ]; $this->assertEquals( 2, TestableDolibarrSyncService::countWithMission([FunctionEnum::TEACHER()->getValue()], $members) ); $this->assertEquals( 3, TestableDolibarrSyncService::countWithMission( [FunctionEnum::TEACHER()->getValue(), FunctionEnum::TREASURER()->getValue()], $members ) ); $this->assertEquals( 1, TestableDolibarrSyncService::countWithMission([FunctionEnum::STUDENT()->getValue()], $members) ); $this->assertEquals( 0, TestableDolibarrSyncService::countWithMission([FunctionEnum::ARCHIVIST()->getValue()], $members) ); } public function testGetPersonContact() { $person = $this->getMockBuilder(Person::class)->getMock(); $contactPoint1 = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint2 = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint1->method('getContactType')->willReturn(ContactPointTypeEnum::OTHER()->getValue()); $contactPoint2->method('getContactType')->willReturn(ContactPointTypeEnum::PRINCIPAL()->getValue()); $person->expects($this->once())->method('getContactPoints')->willReturn(new ArrayCollection([$contactPoint1, $contactPoint2])); $syncService = $this->newDolibarrSyncService(); $this->assertEquals( $contactPoint2, $syncService->getPersonContact($person) ); $person2 = $this->getMockBuilder(Person::class)->getMock(); $person2->expects($this->once())->method('getContactPoints')->willReturn(new ArrayCollection([])); $this->assertEquals(null, $syncService->getPersonContact($person2)); } public function testFormatContactPosition() { $this->translator->method('trans')->willReturnMap( [ [FunctionEnum::PRESIDENT()->getValue(), ['gender' => 'X'], null, null, 'Président(e)'], [FunctionEnum::PRESIDENT()->getValue(), ['gender' => 'M'], null, null, 'Président'], [FunctionEnum::PRESIDENT()->getValue(), ['gender' => 'F'], null, null, 'Présidente'], [FunctionEnum::DIRECTOR()->getValue(), ['gender' => 'X'], null, null, 'Directeur(ice)'], [FunctionEnum::DIRECTOR()->getValue(), ['gender' => 'M'], null, null, 'Directeur'], [FunctionEnum::DIRECTOR()->getValue(), ['gender' => 'F'], null, null, 'Directrice'], ] ); $syncService = $this->newDolibarrSyncService(); $this->assertEquals( 'Président(e)', $syncService->formatContactPosition([FunctionEnum::PRESIDENT()->getValue()]) ); $this->assertEquals( 'Président', $syncService->formatContactPosition([FunctionEnum::PRESIDENT()->getValue()], 'MISTER') ); $this->assertEquals( 'Présidente', $syncService->formatContactPosition([FunctionEnum::PRESIDENT()->getValue()], 'MISS') ); $this->assertEquals( 'Présidente, Directrice', $syncService->formatContactPosition( [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::DIRECTOR()->getValue()], 'MISS' ) ); $this->assertEquals( 'Président, Directeur', $syncService->formatContactPosition( [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::DIRECTOR()->getValue(), FunctionEnum::ADHERENT()->getValue()], 'MISTER' ) ); } public function testFormatPhoneNumber() { $phoneUtil = PhoneNumberUtil::getInstance(); $phoneNumber = $phoneUtil->parse('01 02 03 04 05', "FR"); $this->assertEquals( '+33102030405', TestableDolibarrSyncService::formatPhoneNumber($phoneNumber) ); } }