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->addressPostalUtils = $this->getMockBuilder(AddressPostalUtils::class) ->disableOriginalConstructor() ->getMock(); $this->arrayUtils = $this->getMockBuilder(ArrayUtils::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(); } private function getMockForMethod(string $method) { $dolibarrSyncService = $this->getMockBuilder(TestableDolibarrSyncService::class) ->setConstructorArgs([$this->organizationRepository, $this->accessRepository, $this->functionTypeRepository, $this->dolibarrApiService, $this->addressPostalUtils, $this->arrayUtils, $this->translator]) ->setMethodsExcept([$method, 'setLoggerInterface']) ->getMock(); $dolibarrSyncService->setLoggerInterface($this->logger); return $dolibarrSyncService; } /** * Full test of the scan method * * @see DolibarrSyncService::scan() */ public function testScan(): void { $dolibarrSyncService = $this->getMockForMethod('scan'); // ----- Opentalent Organizations ----- $orgId1 = 10; $organization1 = $this->getMockBuilder(Organization::class)->getMock(); $organization1->method('getId')->willReturn($orgId1); $organization1->method('getName')->willReturn('Organization 10'); $organizationData1 = [ 'fullAddress' => '1 Rue Azerty', 'addressOwner' => 'Mr Keyboard', 'postalCode' => '01110', 'city' => 'ByteCity', 'email' => 'foo@bar.net', 'phone' => '0102030405', 'networkId' => NetworkEnum::CMF()->getValue(), 'product' => SettingsProductEnum::SCHOOL()->getValue() ]; $orgId2 = 20; $organization2 = $this->getMockBuilder(Organization::class)->getMock(); $organization2->method('getId')->willReturn($orgId2); $organization2->method('getName')->willReturn('Organization 20'); $organizationData2 = [ 'email' => null, 'phone' => null, 'networkId' => null, 'product' => SettingsProductEnum::ARTIST()->getValue() ]; $orgId3 = 30; $organization3 = null; // This organization does not exist // Persons $accessId1 = 11; // Person 1 $accessId2 = 21; // Person 2 $accessId3 = 12; // Shall be ignored, because not an office member // access 4 does not exist $accessId5 = 13; // Invalid Person $personId1 = 100; $personData1 = [ 'name' => 'Dupont', 'givenName' => 'Hercules', 'gender' => 'Mr', 'email' => 'an@email.net', 'phone' => '0102030405', 'mobilePhone' => '0607080910', ]; $personId2 = 200; $personData2 = [ 'name' => 'Simpson', 'givenName' => 'Lisa', 'gender' => null, ]; $personId3 = 300; // Obsolete contact, does not exist anymore in the Opentalent DB $personId4 = 400; // Obsolete contact, does not exist anymore in the Opentalent DB $personId5 = 900; // Invalid contact with no firstname and no lastname $personData5 = [ 'name' => '', 'givenName' => '', 'gender' => null, ]; $activeMembers1 = [ $accessId1 => [FunctionEnum::PRESIDENT()->getValue()], $accessId3 => [FunctionEnum::STUDENT()->getValue()], $accessId5 => [FunctionEnum::TREASURER()->getValue()] ]; $activeMembers2 = [ $accessId2 => [FunctionEnum::PRESIDENT()->getValue()] ]; // ----- Opentalent : other vars ----- $cmfId = 12097; $cmfDolibarrId = 12098; $ffecId = 91295; $ffecDolibarrId = 91296; // ----- Dolibarr societies ----- // Existing society about to be updated $socId1 = 1; $dolibarrSociety1 = [ 'id' => $socId1, 'name' => 'Organization 10', 'address' => '1 Rue Qwerty', 'zip' => '01024', 'town' => 'Ram', 'email' => 'some@email.com', 'phone' => null, 'status' => 0, 'parent' => '0', 'array_options' => [ 'options_2iopeninfoopentalent' => '', 'options_2iopen_software_opentalent' => 'Opentalent Artist' ] ]; // Existing society with no data $socId2 = 2; $dolibarrSociety2 = [ 'id' => $socId2, "array_options" => [] ]; // This organization does not exist in the opentalent DB $socId3 = 3; $dolibarrSociety3 = null; // Dolibarr contacts $contactData1 = [ 'id' => '1', 'civility_code' => '', 'lastname' => 'Dupond', 'firstname' => 'Bob', 'email' => 'abcd@mail.com', 'phone_pro' => '+33478570000', 'phone_mobile' => '+33682980000', 'poste' => 'Secrétaire', 'statut' => '1', 'array_options' => [ 'options_2iopen_person_id' => '' ] ]; // An obsolete contact that should be disabled $obsoleteContactData = [ 'id' => '4', 'lastname' => 'Doe', 'firstname' => 'John', 'statut' => '1', 'array_options' => [ 'options_2iopen_person_id' => $personId3 ] ]; // An obsolete contact that should is already disabled $obsoleteContactData2 = [ 'id' => '5', 'lastname' => 'Foo', 'firstname' => 'John', 'statut' => '0', 'array_options' => [ 'options_2iopen_person_id' => $personId4 ] ]; $dolibarrSocietyContacts1 = [$contactData1, $obsoleteContactData, $obsoleteContactData2]; $dolibarrSocietyContacts2 = []; // ----- Setup Mocks ----- $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"], ['school', [], null, null, 'Opentalent School'], ['artist', [], null, null, 'Opentalent Artist'], ['Mr', [], null, null, 'MR'], ]); // Get societies $this->organizationRepository->method('find') ->willReturnMap([ [$orgId1, null, null, $organization1], [$orgId2, null, null, $organization2], [$orgId3, null, null, $organization3] ]); $dolibarrSyncService ->expects(self::once()) ->method('getDolibarrSocietiesIndex') ->willReturn([ $orgId1 => $dolibarrSociety1, $orgId2 => $dolibarrSociety2, $orgId3 => $dolibarrSociety3, ]); $dolibarrSyncService ->expects(self::once()) ->method('getActiveMembersIndex') ->willReturn([ $orgId1 => $activeMembers1, $orgId2 => $activeMembers2, $orgId3 => [] ]); // 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]); // Get CMF and FFEC ids $this->dolibarrApiService->method('getSociety')->willReturnMap( [ [$cmfId, ['id' => $cmfDolibarrId]], [$ffecId, ['id' => $ffecDolibarrId]] ] ); // -- Loop over organizations -- $dolibarrSyncService ->expects(self::exactly(5)) // 3 organizations and 2 contacts ->method('sanitizeDolibarrData') ->willReturnCallback(function ($args) { return $args; }); $addressPostal = $this->getMockBuilder(AddressPostal::class)->getMock(); $dolibarrSyncService ->expects(self::exactly(2)) ->method('getOrganizationPostalAddress') ->willReturnMap([ [$organization1, $addressPostal], [$organization2, null], ]); $this->addressPostalUtils ->method('getFullStreetAddress') ->with($addressPostal) ->willReturn($organizationData1['fullAddress']); $addressPostal->method('getAddressOwner')->willReturn($organizationData1['addressOwner']); $addressPostal->method('getPostalCode')->willReturn($organizationData1['postalCode']); $addressPostal->method('getAddressCity')->willReturn($organizationData1['city']); $dolibarrSyncService ->expects(self::exactly(2)) ->method('getOrganizationEmail') ->willReturnMap([ [$organization1, $organizationData1['email']], [$organization2, $organizationData2['email']], ]); $dolibarrSyncService ->expects(self::exactly(2)) ->method('getOrganizationPhone') ->willReturnMap([ [$organization1, $organizationData1['phone']], [$organization2, $organizationData2['phone']], ]); $dolibarrSyncService ->expects(self::exactly(2)) ->method('getOrganizationNetworkId') ->willReturnMap([ [$organization1, $organizationData1['networkId']], [$organization2, $organizationData2['networkId']], ]); $settings1 = $this->getMockBuilder(Settings::class)->getMock(); $settings1->method('getProduct')->willReturn($organizationData1['product']); $organization1->method('getSettings')->willReturn($settings1); $settings2 = $this->getMockBuilder(Settings::class)->getMock(); $settings1->method('getProduct')->willReturn($organizationData2['product']); $organization2->method('getSettings')->willReturn($settings2); $dolibarrSyncService->method('countWithMission')->willReturnMap([ [[FunctionEnum::STUDENT()->getValue()], $activeMembers1, 1], [[FunctionEnum::ADHERENT()->getValue()], $activeMembers1, 2], [[FunctionEnum::DIRECTOR()->getValue(), FunctionEnum::PRESIDENT()->getValue()], $activeMembers1, 1], [[FunctionEnum::DIRECTOR()->getValue(), FunctionEnum::PRESIDENT()->getValue()], $activeMembers2, 2] ]); $this->arrayUtils ->expects(self::exactly(3)) ->method('getChanges') ->willReturnCallback( function (array $initialArray, array $newArray, bool $recursive = false, ?callable $callback = null) { if (in_array('name', $newArray, true)) { // Organization 1 name is already defined and has not been changed unset($newArray['name']); } if (in_array('statut', $newArray, true)) { // Contact 1 statut is already defined and has not been changed unset($newArray['statut']); } return $newArray; } ); $this->dolibarrApiService->method('getContacts')->willReturnMap([ [$socId1, $dolibarrSocietyContacts1], [$socId2, $dolibarrSocietyContacts2] ]); // Loop over contacts // NB: Student will be skipped since it has no office role $person1 = $this->getMockBuilder(Person::class)->getMock(); $person1->method('getId')->willReturn($personId1); $person1->method('getName')->willReturn($personData1['name']); $person1->method('getGivenName')->willReturn($personData1['givenName']); $person1->method('getGender')->willReturn($personData1['gender']); $person2 = $this->getMockBuilder(Person::class)->getMock(); $person2->method('getId')->willReturn($personId2); $person2->method('getName')->willReturn($personData2['name']); $person2->method('getGivenName')->willReturn($personData2['givenName']); $person2->method('getGender')->willReturn($personData2['gender']); // An invalid person that should be ignored $person5 = $this->getMockBuilder(Person::class)->getMock(); $person5->method('getId')->willReturn($personId5); $person5->method('getName')->willReturn($personData5['name']); $person5->method('getGivenName')->willReturn($personData5['givenName']); $access1 = $this->getMockBuilder(Access::class)->getMock(); $access1->method('getPerson')->willReturn($person1); $access2 = $this->getMockBuilder(Access::class)->getMock(); $access2->method('getPerson')->willReturn($person2); $access5 = $this->getMockBuilder(Access::class)->getMock(); $access5->method('getPerson')->willReturn($person5); $this->accessRepository->method('find')->willReturnMap([ [$accessId1, null, null, $access1], [$accessId2, null, null, $access2], [$accessId5, null, null, $access5], ]); $dolibarrSyncService->method('findDolibarrContactFor')->willReturnMap([ [$dolibarrSocietyContacts1, $person1, $contactData1], [$dolibarrSocietyContacts2, $person2, null] ]); $contactPoint1 = $this->getMockBuilder(ContactPoint::class)->getMock(); $contactPoint1->method('getEmail')->willReturn($personData1['email']); $phone = $this->getMockBuilder(PhoneNumber::class)->getMock(); $mobilePhone = $this->getMockBuilder(PhoneNumber::class)->getMock(); $dolibarrSyncService->method('formatPhoneNumber')->willReturnMap([ [$phone, $personData1['phone']], [$mobilePhone, $personData1['mobilePhone']], ]); $contactPoint1->method('getTelphone')->willReturn($phone); $contactPoint1->method('getMobilPhone')->willReturn($mobilePhone); $dolibarrSyncService->method('getPersonContact')->willReturnMap([ [$person1, $contactPoint1], [$person2, null], ]); $dolibarrSyncService->method('formatContactPosition')->willReturnMap([ [[FunctionEnum::PRESIDENT()->getValue()], 'Mr', 'Président'], [[FunctionEnum::PRESIDENT()->getValue()], null, 'Président(e)'], ]); // Expected logged error messages $this->logger->expects(self::exactly(2))->method('error')->withConsecutive( ["Person 900 miss a lastname and/or a firstname, ignored."], ["Organization 30 not found in the Opentalent DB"], ); // Expected progression callback triggers $progressionCallbackExpectedCalls = [[1, 3], [2, 3], [3, 3]]; $progressionCallback = static function ($i, $total) use (&$progressionCallbackExpectedCalls) { [$expectedI, $expectedTotal] = array_shift($progressionCallbackExpectedCalls); if ($i !== $expectedI || $total !== $expectedTotal) { throw new \AssertionError( 'Progression callback error, expected parameters are (' . $expectedI . ',' . $expectedTotal . ')' . ', got (' . $i . ', ' . $total . ')' ); } }; $operations = $dolibarrSyncService->scan($progressionCallback); $this->assertCount(5, $operations); $this->assertEqualsCanonicalizing( [ '[PUT thirdparties/1]', "address : `1 Rue Qwerty` => `Mr Keyboard\n1 Rue Azerty`", 'zip : `01024` => `01110`', 'town : `Ram` => `ByteCity`', 'email : `some@email.com` => `foo@bar.net`', 'phone : `` => `0102030405`', 'parent : `0` => `12098`', "array_options.options_2iopen_software_opentalent : `Opentalent Artist` => `Opentalent School`", "array_options.options_2iopeninfoopentalent : `` => `Nombre d'élèves : 1\nNombre d'adhérents : 2\nNombre d'accès admin : 1`", 'status : `0` => `1`' ], $operations[0]->getChangeLog() ); $this->assertEqualsCanonicalizing( [ '[PUT contacts/1]', 'civility_code : `` => `MR`', 'lastname : `Dupond` => `Dupont`', 'firstname : `Bob` => `Hercules`', 'email : `abcd@mail.com` => `an@email.net`', 'phone_pro : `+33478570000` => `0102030405`', 'phone_mobile : `+33682980000` => `0607080910`', 'poste : `Secrétaire` => `Président`', 'array_options.options_2iopen_person_id : `` => `100`' ], $operations[1]->getChangeLog() ); $this->assertEqualsCanonicalizing( ['[PUT contacts/4]', 'statut : `1` => `0`'], $operations[2]->getChangeLog() ); $this->assertEqualsCanonicalizing( [ '[PUT thirdparties/2]', 'address : (new) => ``', 'email : (new) => ``', 'name : (new) => `Organization 20`', 'parent : (new) => ``', 'phone : (new) => ``', 'status : (new) => `1`', 'town : (new) => ``', 'zip : (new) => ``', 'array_options.options_2iopeninfoopentalent : (new) => `Nombre d\'accès admin : 2`', ], $operations[3]->getChangeLog() ); $this->assertEqualsCanonicalizing( [ '[POST contacts]', 'civility_code : (new) => ``', 'lastname : (new) => `Simpson`', 'firstname : (new) => `Lisa`', 'email : (new) => ``', 'phone_pro : (new) => ``', 'phone_mobile : (new) => ``', 'poste : (new) => `Président(e)`', 'statut : (new) => `1`', 'array_options.options_2iopen_person_id : (new) => `200`', 'socid : (new) => `2`' ], $operations[4]->getChangeLog() ); $this->assertCount(0, $progressionCallbackExpectedCalls); } /** * All valid operations shall be executed * If an operation is not in status READY, a warning shall be logged, and the operation shall be skipped * * @see DolibarrSyncService::execute() */ public function testExecute(): void { $dolibarrSyncService = $this->getMockForMethod('execute'); $progressionCallbackExpectedCalls = [[1, 3], [2, 3], [3, 3]]; $progressionCallback = static function ($i, $total) use (&$progressionCallbackExpectedCalls) { [$expectedI, $expectedTotal] = array_shift($progressionCallbackExpectedCalls); if ($i !== $expectedI || $total !== $expectedTotal) { throw new \AssertionError( 'Progression callback error, expected parameters are (' . $expectedI . ',' . $expectedTotal . ')' . ', got (' . $i . ', ' . $total . ')' ); } }; $response = $this->getMockBuilder(ResponseInterface::class)->disableOriginalConstructor()->getMock(); $operation1 = $this->getMockBuilder(UpdateOperation::class)->disableOriginalConstructor()->getMock(); $operation1->method('getStatus')->willReturnOnConsecutiveCalls(BaseRestOperation::STATUS_READY, BaseRestOperation::STATUS_DONE); $operation1->method('getChangeLog')->willReturn(['foo']); $operation1->expects(self::once())->method('execute')->willReturn($response); $dolibarrSyncService->method('validateResponse')->with($response, $operation1)->willThrowException(new RuntimeException()); $operation2 = $this->getMockBuilder(CreateOperation::class)->disableOriginalConstructor()->getMock(); $operation2->method('getStatus')->willReturn( BaseRestOperation::STATUS_READY, BaseRestOperation::STATUS_ERROR, BaseRestOperation::STATUS_ERROR // An error happened ); $operation2->expects(self::once())->method('execute'); $operation3 = $this->getMockBuilder(DeleteOperation::class)->disableOriginalConstructor()->getMock(); $operation3->method('getStatus')->willReturn(BaseRestOperation::STATUS_DONE); // Invalid status, should log a warning and not execute $operation3->expects(self::never())->method('execute'); $this->logger->expects(self::exactly(3))->method('warning'); // 1 warning from validateResponse on the Update Op, and 2 because of the bad status of the Create Op $this->logger->expects(self::exactly(3))->method('error'); // The exception thrown during the execution of the Delete op will log 3 errors $dolibarrSyncService->execute([$operation1, $operation2, $operation3], $progressionCallback); } /** * @see DolibarrSyncService::run() */ public function testRun() { $dolibarrSyncService = $this->getMockForMethod('run'); $operations = ['operation1', 'operation2']; $dolibarrSyncService->expects(self::once())->method('scan')->willReturn($operations); $dolibarrSyncService->expects(self::once())->method('execute')->with($operations); $result = $dolibarrSyncService->run(); $this->assertEquals($operations, $result); } /** * @see DolibarrSyncService::getDolibarrSocietiesIndex() */ public function testGetDolibarrSocietiesIndex(): void { $dolibarrSyncService = $this->getMockForMethod('getDolibarrSocietiesIndex'); $this->dolibarrApiService ->expects($this->once()) ->method('getAllClients') ->willReturn( [ ['id' => 1, 'array_options' => ['options_2iopen_organization_id' => 101]], ['id' => 2, 'array_options' => ['options_2iopen_organization_id' => 102]], ['id' => 3, 'array_options' => ['options_2iopen_organization_id' => null]], // No org id but also no contract, so it's ok ['id' => 4, 'name' => 'foo', 'array_options' => ['options_2iopen_organization_id' => null]], // No org id but has a contract, a warning should be logged ] ); $this->dolibarrApiService->expects(self::exactly(2))->method('getActiveContract')->willReturnMap([ [3, null], [4, ['dummy non-empty data']] ]); $this->logger->expects(self::once())->method('warning')->with('Dolibarr client has no organization id: foo (4)'); $index = $dolibarrSyncService->getDolibarrSocietiesIndex(); $this->assertEqualsCanonicalizing( [ 1 => ['id' => 1, 'array_options' => ['options_2iopen_organization_id' => 101]], 2 => ['id' => 2, 'array_options' => ['options_2iopen_organization_id' => 102]] ], $index ); } /** * @see DolibarrSyncService::getActiveMembersIndex() */ public function testGetActiveMembersIndex(): void { $dolibarrSyncService = $this->getMockForMethod('getActiveMembersIndex'); $this->accessRepository ->expects($this->once()) ->method('getAllActiveMembersAndMissions') ->willReturn( [ ['id' => 1, 'organization_id' => 1, 'mission' => FunctionEnum::PRESIDENT()->getValue()], ['id' => 2, 'organization_id' => 1, 'mission' => FunctionEnum::STUDENT()->getValue()], ['id' => 3, 'organization_id' => 2, 'mission' => FunctionEnum::PRESIDENT()->getValue()], ['id' => 3, 'organization_id' => 2, 'mission' => FunctionEnum::TEACHER()->getValue()] ] ); $index = $dolibarrSyncService->getActiveMembersIndex(); $this->assertEqualsCanonicalizing([ 1 => [1 => [FunctionEnum::PRESIDENT()->getValue()], 2 => [FunctionEnum::STUDENT()->getValue()]], 2 => [3 => [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::TEACHER()->getValue()]] ], $index); } /** * @see DolibarrSyncService::findDolibarrContactFor() */ public function testFindDolibarrContactForById(): void { $dolibarrSyncService = $this->getMockForMethod('findDolibarrContactFor'); $contacts = [ ['id' => 1, 'array_options' => ['options_2iopen_person_id' => 101]], ['id' => 2, 'array_options' => ['options_2iopen_person_id' => 102]], ]; // Find by id $person = $this->getMockBuilder(Person::class)->getMock(); $person->method('getId')->willReturn(102); $contact = $dolibarrSyncService->findDolibarrContactFor($contacts, $person); $this->assertEquals(2, $contact['id']); } /** * @see DolibarrSyncService::findDolibarrContactFor() */ public function testFindDolibarrContactForByName(): void { $dolibarrSyncService = $this->getMockForMethod('findDolibarrContactFor'); $contacts = [ ['id' => 1, 'firstname' => 'mister', 'lastname' => 'X', 'array_options' => ['options_2iopen_person_id' => null]], ['id' => 2, 'firstname' => 'miss', 'lastname' => 'Y', 'array_options' => ['options_2iopen_person_id' => null]], ]; // Find by full name (contact has no person id, it should be returned) $person = $this->getMockBuilder(Person::class)->getMock(); $person->method('getId')->willReturn(101); $person->method('getName')->willReturn('X'); $person->method('getGivenName')->willReturn('mister'); $result = $dolibarrSyncService->findDolibarrContactFor($contacts, $person); $this->assertEquals(1, $result['id']); } /** * @see DolibarrSyncService::findDolibarrContactFor() */ public function testFindDolibarrContactForByNameWithConflict(): void { $dolibarrSyncService = $this->getMockForMethod('findDolibarrContactFor'); $contacts = [ ['id' => 1, 'firstname' => 'mister', 'lastname' => 'X', 'array_options' => ['options_2iopen_person_id' => 1]], ['id' => 2, 'firstname' => 'miss', 'lastname' => 'Y', 'array_options' => ['options_2iopen_person_id' => 2]], ]; // Find by full name (contact already has another person id, it should not be returned) $person = $this->getMockBuilder(Person::class)->getMock(); $person->method('getId')->willReturn(101); $person->method('getName')->willReturn('X'); $person->method('getGivenName')->willReturn('mister'); $result = $dolibarrSyncService->findDolibarrContactFor($contacts, $person); $this->assertEquals(null, $result); } /** * @see DolibarrSyncService::findDolibarrContactFor() */ public function testFindDolibarrContactNotFound(): void { $dolibarrSyncService = $this->getMockForMethod('findDolibarrContactFor'); $contacts = [ ['id' => 1, 'firstname' => 'mister', 'lastname' => 'X', 'array_options' => ['options_2iopen_person_id' => 1]], ['id' => 2, 'firstname' => 'miss', 'lastname' => 'Y', 'array_options' => ['options_2iopen_person_id' => 2]], ]; // Do not find $person = $this->getMockBuilder(Person::class)->getMock(); $person->method('getId')->willReturn(-1); $person->method('getName')->willReturn('Presley'); $person->method('getGivenName')->willReturn('Elvis'); $result = $dolibarrSyncService->findDolibarrContactFor($contacts, $person); $this->assertEquals(null, $result); } /** * @see DolibarrSyncService::sanitizeDolibarrData() */ public function testSanitizeDolibarrData(): void { $dolibarrSyncService = $this->getMockForMethod('sanitizeDolibarrData'); $result = $dolibarrSyncService->sanitizeDolibarrData(['a' => 'A', 'b' => '', 'c' => ['d' => 'D', 'e' => '']]); $this->assertEquals( ['a' => 'A', 'b' => null, 'c' => ['d' => 'D', 'e' => null]], $result ); } /** * @see DolibarrSyncService::sanitizeDolibarrData() */ public function testSanitizeDolibarrDataWithNull(): void { $dolibarrSyncService = $this->getMockForMethod('sanitizeDolibarrData'); $result = $dolibarrSyncService->sanitizeDolibarrData(null); $this->assertEquals(null, $result); } /** * @see DolibarrSyncService::getOrganizationPostalAddress() */ public function testGetOrganizationPostalAddress(): void { $dolibarrSyncService = $this->getMockForMethod('getOrganizationPostalAddress'); $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]) ); $this->assertEquals( $addressPostal, $dolibarrSyncService->getOrganizationPostalAddress($organization) ); } /** * @see DolibarrSyncService::getOrganizationPostalAddress() */ public function testGetOrganizationPostalAddressNoResult(): void { $dolibarrSyncService = $this->getMockForMethod('getOrganizationPostalAddress'); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization->expects($this->once()) ->method('getOrganizationAddressPostals') ->willReturn(new ArrayCollection([])); $this->assertEquals( null, $dolibarrSyncService->getOrganizationPostalAddress($organization) ); } /** * @see DolibarrSyncService::getOrganizationPhone() */ public function testGetOrganizationPhoneWithExistingPhone(): void { $dolibarrSyncService = $this->getMockForMethod('getOrganizationPhone'); $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()); $phone = $this->getMockBuilder(PhoneNumber::class)->disableOriginalConstructor()->getMock(); $contactPoint2->method('getTelphone')->willReturn($phone); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization ->expects($this->once()) ->method('getContactPoints') ->willReturn( new ArrayCollection([$contactPoint1, $contactPoint2, $contactPoint3]) ); $dolibarrSyncService->expects(self::once())->method('formatPhoneNumber')->with($phone)->willReturn('+33161626365'); $this->assertEquals( '+33161626365', $dolibarrSyncService->getOrganizationPhone($organization) ); } /** * @see DolibarrSyncService::getOrganizationPhone() */ public function testGetOrganizationPhoneWithMobilePhone() { $dolibarrSyncService = $this->getMockForMethod('getOrganizationPhone'); $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); $mobilePhone = $this->getMockBuilder(PhoneNumber::class)->disableOriginalConstructor()->getMock(); $contactPoint2->method('getMobilPhone')->willReturn($mobilePhone); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization ->expects($this->once()) ->method('getContactPoints') ->willReturn( new ArrayCollection([$contactPoint1, $contactPoint2, $contactPoint3]) ); $dolibarrSyncService->expects(self::once())->method('formatPhoneNumber')->with($mobilePhone)->willReturn('+33661626365'); $this->assertEquals( '+33661626365', $dolibarrSyncService->getOrganizationPhone($organization) ); } /** * @see DolibarrSyncService::getOrganizationPhone() */ public function testGetOrganizationPhoneWithNoPhone() { $dolibarrSyncService = $this->getMockForMethod('getOrganizationPhone'); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization ->expects($this->once()) ->method('getContactPoints') ->willReturn(new ArrayCollection([])); $dolibarrSyncService->expects(self::never())->method('formatPhoneNumber'); $this->assertEquals( null, $dolibarrSyncService->getOrganizationPhone($organization) ); } /** * @see DolibarrSyncService::getOrganizationEmail() */ public function testGetOrganizationEmailWithExistingEmail() { $dolibarrSyncService = $this->getMockForMethod('getOrganizationEmail'); $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 = $this->getMockBuilder(Organization::class)->getMock(); $organization ->expects($this->once()) ->method('getContactPoints') ->willReturn( new ArrayCollection([$contactPoint1, $contactPoint2, $contactPoint3]) ); $this->assertEquals( 'email@email.com', $dolibarrSyncService->getOrganizationEmail($organization) ); } /** * @see DolibarrSyncService::getOrganizationEmail() */ public function testGetOrganizationEmailWithNoEmail() { $dolibarrSyncService = $this->getMockForMethod('getOrganizationEmail'); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization ->expects($this->once()) ->method('getContactPoints') ->willReturn(new ArrayCollection([])); $this->assertEquals( null, $dolibarrSyncService->getOrganizationEmail($organization) ); } /** * @see DolibarrSyncService::getOrganizationNetworkId() */ public function testGetOrganizationNetworkId() { $dolibarrSyncService = $this->getMockForMethod('getOrganizationNetworkId'); $organization = $this->getMockBuilder(Organization::class)->getMock(); $network = $this->getMockBuilder(Network::class)->getMock(); $network->method('getId')->willReturn(3); $networkOrganization = $this->getMockBuilder(NetworkOrganization::class)->getMock(); $networkOrganization->method('getNetwork')->willReturn($network); $organization->method('getNetworkOrganizations')->willReturn(new ArrayCollection([$networkOrganization])); $this->assertEquals( 3, $dolibarrSyncService->getOrganizationNetworkId($organization) ); } /** * @see DolibarrSyncService::getOrganizationNetworkId() */ public function testGetOrganizationNetworkIdWithMultipleResult() { $dolibarrSyncService = $this->getMockForMethod('getOrganizationNetworkId'); $network1 = $this->getMockBuilder(Network::class)->getMock(); $network1->method('getId')->willReturn(3); $networkOrganization1 = $this->getMockBuilder(NetworkOrganization::class)->getMock(); $networkOrganization1->method('getNetwork')->willReturn($network1); $networkOrganization1->method('getEndDate')->willReturn(new \DateTime('2000-01-01')); $network2 = $this->getMockBuilder(Network::class)->getMock(); $network2->method('getId')->willReturn(4); $networkOrganization2 = $this->getMockBuilder(NetworkOrganization::class)->getMock(); $networkOrganization2->method('getNetwork')->willReturn($network2); $networkOrganization2->method('getEndDate')->willReturn(null); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization->method('getNetworkOrganizations')->willReturn( new ArrayCollection([$networkOrganization1, $networkOrganization2]) ); $this->assertEquals( 4, $dolibarrSyncService->getOrganizationNetworkId($organization) ); } /** * @see DolibarrSyncService::getOrganizationNetworkId() */ public function testGetOrganizationNetworkIdWithNoResult() { $dolibarrSyncService = $this->getMockForMethod('getOrganizationNetworkId'); $organization = $this->getMockBuilder(Organization::class)->getMock(); $network = $this->getMockBuilder(Network::class)->getMock(); $network->method('getId')->willReturn(3); $networkOrganization = $this->getMockBuilder(NetworkOrganization::class)->getMock(); $networkOrganization->method('getNetwork')->willReturn($network); $networkOrganization->method('getEndDate')->willReturn(new \DateTime('2000-01-01')); $organization->method('getNetworkOrganizations')->willReturn(new ArrayCollection([$networkOrganization])); $this->assertEquals( null, $dolibarrSyncService->getOrganizationNetworkId($organization) ); } /** * @see DolibarrSyncService::countWithMission() */ public function testCountWithMission() { $dolibarrSyncService = $this->getMockForMethod('countWithMission'); $members = [ 123 => [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::TEACHER()->getValue()], 124 => [FunctionEnum::TEACHER()->getValue()], 125 => [FunctionEnum::STUDENT()->getValue()], 126 => [FunctionEnum::TREASURER()->getValue()], ]; $this->assertEquals( 2, $dolibarrSyncService->countWithMission([FunctionEnum::TEACHER()->getValue()], $members) ); $this->assertEquals( 3, $dolibarrSyncService->countWithMission( [FunctionEnum::TEACHER()->getValue(), FunctionEnum::TREASURER()->getValue()], $members ) ); $this->assertEquals( 1, $dolibarrSyncService->countWithMission([FunctionEnum::STUDENT()->getValue()], $members) ); $this->assertEquals( 0, $dolibarrSyncService->countWithMission([FunctionEnum::ARCHIVIST()->getValue()], $members) ); } /** * @see DolibarrSyncService::getPersonContact() */ public function testGetPersonContact() { $dolibarrSyncService = $this->getMockForMethod('getPersonContact'); $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])); $this->assertEquals( $contactPoint2, $dolibarrSyncService->getPersonContact($person) ); $person2 = $this->getMockBuilder(Person::class)->getMock(); $person2->expects($this->once())->method('getContactPoints')->willReturn(new ArrayCollection([])); $this->assertEquals( null, $dolibarrSyncService->getPersonContact($person2) ); } /** * @see DolibarrSyncService::formatContactPosition() */ public function testFormatContactPosition() { $dolibarrSyncService = $this->getMockForMethod('formatContactPosition'); $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'], [FunctionEnum::TEACHER()->getValue(), ['gender' => 'X'], null, null, 'Professeur(e)'], [FunctionEnum::ARCHIVIST()->getValue(), ['gender' => 'X'], null, null, 'Archiviste'], [FunctionEnum::TREASURER()->getValue(), ['gender' => 'X'], null, null, 'Trésorier(ère)'], [FunctionEnum::ADMINISTRATIVE_STAFF()->getValue(), ['gender' => 'X'], null, null, 'Personnel administratif'], ] ); $this->assertEquals( 'Président(e)', $dolibarrSyncService->formatContactPosition([FunctionEnum::PRESIDENT()->getValue()]) ); $this->assertEquals( 'Président', $dolibarrSyncService->formatContactPosition([FunctionEnum::PRESIDENT()->getValue()], 'MISTER') ); $this->assertEquals( 'Présidente', $dolibarrSyncService->formatContactPosition([FunctionEnum::PRESIDENT()->getValue()], 'MISS') ); $this->assertEquals( 'Présidente, Directrice', $dolibarrSyncService->formatContactPosition( [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::DIRECTOR()->getValue()], 'MISS' ) ); $this->assertEquals( 'Président, Directeur', $dolibarrSyncService->formatContactPosition( [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::DIRECTOR()->getValue(), FunctionEnum::ADHERENT()->getValue()], 'MISTER' ) ); $this->assertEquals( 'Président, Directeur', $dolibarrSyncService->formatContactPosition( [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::DIRECTOR()->getValue(), FunctionEnum::ADHERENT()->getValue()], 'MISTER' ) ); $this->assertEquals( 'Président(e), Directeur(ice), Professeur(e), Archiviste, Trésorier(ère), Pers...', $dolibarrSyncService->formatContactPosition( [ FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::DIRECTOR()->getValue(), FunctionEnum::TEACHER()->getValue(), FunctionEnum::ARCHIVIST()->getValue(), FunctionEnum::TREASURER()->getValue(), FunctionEnum::ADMINISTRATIVE_STAFF()->getValue(), ], 'X' ) ); } /** * @see DolibarrSyncService::formatPhoneNumber() */ public function testFormatPhoneNumber() { $dolibarrSyncService = $this->getMockForMethod('formatPhoneNumber'); $phoneUtil = PhoneNumberUtil::getInstance(); $phoneNumber = $phoneUtil->parse('01 02 03 04 05', "FR"); $this->assertEquals( '+33102030405', $dolibarrSyncService->formatPhoneNumber($phoneNumber) ); } /** * @see DolibarrSyncService::validateResponse() */ public function testValidateResponse(): void { $dolibarrSyncService = $this->getMockForMethod('validateResponse'); $response = $this->getMockBuilder(ResponseInterface::class)->getMock(); $response->method('toArray')->willReturn(['a' => 1]); $operation = $this->getMockBuilder(CreateOperation::class)->disableOriginalConstructor()->getMock(); $operation->method('getData')->willReturn(['a' => 1]); $dolibarrSyncService->expects(self::exactly(2))->method('sanitizeDolibarrData')->with(['a' => 1])->willReturn(['a' => 1]); $this->arrayUtils->expects(self::once())->method('getChanges')->with(['a' => 1], ['a' => 1], true)->willReturn([]); $dolibarrSyncService->validateResponse($response, $operation); } /** * @see DolibarrSyncService::validateResponse() */ public function testValidateResponseInvalid(): void { $dolibarrSyncService = $this->getMockForMethod('validateResponse'); $response = $this->getMockBuilder(ResponseInterface::class)->getMock(); $response->method('toArray')->willReturn(['a' => 1]); $operation = $this->getMockBuilder(CreateOperation::class)->disableOriginalConstructor()->getMock(); $operation->method('getData')->willReturn(['a' => 0]); $dolibarrSyncService->expects(self::exactly(2)) ->method('sanitizeDolibarrData') ->willReturnMap([ [['a' => 1], ['a' => 1]], [['a' => 0], ['a' => 0]] ]); $this->arrayUtils->expects(self::once())->method('getChanges')->with(['a' => 1], ['a' => 0], true)->willReturn(['a' => 0]); $this->expectException(RuntimeException::class); $dolibarrSyncService->validateResponse($response, $operation); } /** * @see DolibarrSyncService::validateResponse() */ public function testValidateResponseRequestError(): void { $dolibarrSyncService = $this->getMockForMethod('validateResponse'); $response = $this->getMockBuilder(ResponseInterface::class)->getMock(); $response->method('getInfo')->willReturnMap([ ['http_code', '200'], ['url', 'http://url.com'], ['response_headers', []] ]); $response->method('getContent')->willReturn(""); $response->method('toArray')->willThrowException(new ServerException($response)); $operation = $this->getMockBuilder(CreateOperation::class)->disableOriginalConstructor()->getMock(); $operation->method('getData')->willReturn(['a' => 0]); $dolibarrSyncService->expects(self::never())->method('sanitizeDolibarrData'); $this->arrayUtils->expects(self::never())->method('getChanges'); $this->expectException(RuntimeException::class); $dolibarrSyncService->validateResponse($response, $operation); } }