DolibarrSyncServiceTest.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. <?php
  2. namespace App\Tests\Service\Dolibarr;
  3. use App\Entity\Core\AddressPostal;
  4. use App\Entity\Core\ContactPoint;
  5. use App\Entity\Organization\Organization;
  6. use App\Entity\Organization\OrganizationAddressPostal;
  7. use App\Entity\Person\Person;
  8. use App\Enum\Access\FunctionEnum;
  9. use App\Enum\Core\ContactPointTypeEnum;
  10. use App\Enum\Organization\AddressPostalOrganizationTypeEnum;
  11. use App\Repository\Access\AccessRepository;
  12. use App\Repository\Access\FunctionTypeRepository;
  13. use App\Repository\Core\ContactPointRepository;
  14. use App\Repository\Organization\OrganizationRepository;
  15. use App\Service\Dolibarr\DolibarrApiService;
  16. use App\Service\Dolibarr\DolibarrSyncService;
  17. use JetBrains\PhpStorm\Pure;
  18. use libphonenumber\PhoneNumber;
  19. use PHPUnit\Framework\TestCase;
  20. use Psr\Log\LoggerInterface;
  21. use Symfony\Contracts\Translation\TranslatorInterface;
  22. class TestableDolibarrSyncService extends DolibarrSyncService {
  23. public function getDolibarrSocietiesIndex(): array { return parent::getDolibarrSocietiesIndex(); }
  24. public function getDolibarrContactsIndex(int $socId): array { return parent::getDolibarrContactsIndex($socId); }
  25. public function getActiveMembersIndex(): array { return parent::getActiveMembersIndex(); }
  26. public static function sanitizeDolibarrData(?array $data): ?array { return parent::sanitizeDolibarrData($data); }
  27. public function getOrganizationPostalAddress(Organization $organization): AddressPostal { return parent::getOrganizationPostalAddress($organization); }
  28. public function getOrganizationPhone(Organization $organization): ?string { return parent::getOrganizationPhone($organization); }
  29. public function getOrganizationEmail(Organization $organization): ?string { return parent::getOrganizationEmail($organization); }
  30. public static function countWithMission(array $missions, array $members): int { return parent::countWithMission($missions, $members); }
  31. public function getPersonContact(Person $person): ?ContactPoint { return parent::getPersonContact($person); }
  32. public function formatContactPosition(array $missions, ?string $gender = 'X'): string { return parent::formatContactPosition($missions, $gender); }
  33. public static function formatPhoneNumber(PhoneNumber $phoneNumber): string { return parent::formatPhoneNumber($phoneNumber); }
  34. public static function filterDiff(array $initialData, array $newData): array { return parent::filterDiff($initialData, $newData); }
  35. }
  36. class DolibarrSyncServiceTest extends TestCase
  37. {
  38. private OrganizationRepository $organizationRepository;
  39. private AccessRepository $accessRepository;
  40. private ContactPointRepository $contactPointRepository;
  41. private FunctionTypeRepository $functionTypeRepository;
  42. private DolibarrApiService $dolibarrApiService;
  43. private TranslatorInterface $translator;
  44. private LoggerInterface $logger;
  45. public function setUp(): void {
  46. $this->organizationRepository = $this->getMockBuilder(OrganizationRepository::class)
  47. ->disableOriginalConstructor()
  48. ->getMock();
  49. $this->accessRepository = $this->getMockBuilder(AccessRepository::class)
  50. ->disableOriginalConstructor()
  51. ->getMock();
  52. $this->contactPointRepository = $this->getMockBuilder(ContactPointRepository::class)
  53. ->disableOriginalConstructor()
  54. ->getMock();
  55. $this->functionTypeRepository = $this->getMockBuilder(FunctionTypeRepository::class)
  56. ->disableOriginalConstructor()
  57. ->getMock();
  58. $this->dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
  59. ->disableOriginalConstructor()
  60. ->getMock();
  61. $this->translator = $this->getMockBuilder(TranslatorInterface::class)
  62. ->disableOriginalConstructor()
  63. ->getMock();
  64. $this->logger = $this->getMockBuilder(LoggerInterface::class)
  65. ->disableOriginalConstructor()
  66. ->getMock();
  67. }
  68. #[Pure]
  69. private function newDolibarrSyncService(): TestableDolibarrSyncService
  70. {
  71. return new TestableDolibarrSyncService(
  72. $this->organizationRepository,
  73. $this->accessRepository,
  74. $this->contactPointRepository,
  75. $this->functionTypeRepository,
  76. $this->dolibarrApiService,
  77. $this->translator,
  78. $this->logger
  79. );
  80. }
  81. private function getJsonContentFromFixture(string $filename): array {
  82. $filepath = dirname(__FILE__) . '/fixtures/' . $filename;
  83. return json_decode(file_get_contents($filepath), true);
  84. }
  85. public function testGetDolibarrSocietiesIndex() {
  86. $this->dolibarrApiService
  87. ->expects($this->once())
  88. ->method('getAllClients')
  89. ->willReturn(
  90. $this->getJsonContentFromFixture('thirdparties.json')
  91. );
  92. $syncService = $this->newDolibarrSyncService();
  93. $index = $syncService->getDolibarrSocietiesIndex();
  94. $this->assertEquals("13930", $index[13930]['array_options']['options_2iopen_organization_id']);
  95. }
  96. public function testDolibarrContactsIndex() {
  97. $this->dolibarrApiService
  98. ->expects($this->once())
  99. ->method('getOpentalentContacts')
  100. ->with(9)
  101. ->willReturn(
  102. $this->getJsonContentFromFixture('contacts.json')
  103. );
  104. $syncService = $this->newDolibarrSyncService();
  105. $index = $syncService->getDolibarrContactsIndex(9);
  106. $this->assertEquals("302117", $index[302117]['array_options']['options_2iopen_person_id']);
  107. }
  108. public function testActiveMembersIndex() {
  109. $this->accessRepository
  110. ->expects($this->once())
  111. ->method('getAllActiveMembersAndMissions')
  112. ->willReturn(
  113. [
  114. ['id' => 123, 'organization_id' => 1, 'mission' => FunctionEnum::PRESIDENT()->getValue()],
  115. ['id' => 123, 'organization_id' => 1, 'mission' => FunctionEnum::TEACHER()->getValue()],
  116. ['id' => 124, 'organization_id' => 1, 'mission' => FunctionEnum::ADMINISTRATIVE_STAFF()->getValue()],
  117. ['id' => 125, 'organization_id' => 2, 'mission' => FunctionEnum::ADHERENT()->getValue()],
  118. ]
  119. );
  120. $syncService = $this->newDolibarrSyncService();
  121. $this->assertEquals(
  122. [
  123. 1 => [
  124. 123 => [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::TEACHER()->getValue()],
  125. 124 => [FunctionEnum::ADMINISTRATIVE_STAFF()->getValue()]
  126. ],
  127. 2 => [
  128. 125 => [FunctionEnum::ADHERENT()->getValue()]
  129. ]
  130. ],
  131. $syncService->getActiveMembersIndex()
  132. );
  133. }
  134. public function testSanitizeDolibarrData() {
  135. $this->assertEquals(null, TestableDolibarrSyncService::sanitizeDolibarrData(null));
  136. $this->assertEquals(
  137. ['a' => 'A', 'b' => null, 'c' => ['d' => 'D', 'e' => null]],
  138. TestableDolibarrSyncService::sanitizeDolibarrData(
  139. ['a' => 'A', 'b' => '', 'c' => ['d' => 'D', 'e' => '']]
  140. )
  141. );
  142. }
  143. public function testGetOrganizationPostalAddress() {
  144. $organization = $this->getMockBuilder(Organization::class)->getMock();
  145. $organizationAddressPostal1 = $this->getMockBuilder(OrganizationAddressPostal::class)->getMock();
  146. $organizationAddressPostal2 = $this->getMockBuilder(OrganizationAddressPostal::class)->getMock();
  147. $organizationAddressPostal3 = $this->getMockBuilder(OrganizationAddressPostal::class)->getMock();
  148. $addressPostal = $this->getMockBuilder(AddressPostal::class)->getMock();
  149. $organizationAddressPostal1->method('getType')->willReturn(AddressPostalOrganizationTypeEnum::ADDRESS_PRACTICE()->getValue());
  150. $organizationAddressPostal2->method('getType')->willReturn(AddressPostalOrganizationTypeEnum::ADDRESS_BILL()->getValue());
  151. $organizationAddressPostal3->method('getType')->willReturn(AddressPostalOrganizationTypeEnum::ADDRESS_OTHER()->getValue());
  152. $organizationAddressPostal2->method('getAddressPostal')->willReturn($addressPostal);
  153. $organization->expects($this->once())
  154. ->method('getOrganizationAddressPostals')
  155. ->willReturn(
  156. [$organizationAddressPostal1, $organizationAddressPostal2, $organizationAddressPostal3]
  157. );
  158. $syncService = $this->newDolibarrSyncService($organization);
  159. $this->assertEquals(
  160. $addressPostal,
  161. $syncService->getOrganizationPostalAddress($organization)
  162. );
  163. $organization2 = $this->getMockBuilder(Organization::class)->getMock();
  164. $organization->expects($this->once())
  165. ->method('getOrganizationAddressPostals')
  166. ->willReturn([]);
  167. $this->assertEquals(
  168. null,
  169. $syncService->getOrganizationPostalAddress($organization2)
  170. );
  171. }
  172. public function testGetOrganizationPhoneWithExistingPhone()
  173. {
  174. $organization = $this->getMockBuilder(Organization::class)->getMock();
  175. $contactPoint1 = $this->getMockBuilder(ContactPoint::class)->getMock();
  176. $contactPoint2 = $this->getMockBuilder(ContactPoint::class)->getMock();
  177. $contactPoint3 = $this->getMockBuilder(ContactPoint::class)->getMock();
  178. $contactPoint1->method('getContactType')->willReturn(ContactPointTypeEnum::OTHER()->getValue());
  179. $contactPoint2->method('getContactType')->willReturn(ContactPointTypeEnum::BILL()->getValue());
  180. $contactPoint3->method('getContactType')->willReturn(ContactPointTypeEnum::PRINCIPAL()->getValue());
  181. $contactPoint2->expects($this->once())->method('getTelphone')->willReturn('0161626365');
  182. $organization
  183. ->expects($this->once())
  184. ->method('getContactPoints')
  185. ->willReturn(
  186. [$contactPoint1, $contactPoint2, $contactPoint3]
  187. );
  188. $syncService = $this->newDolibarrSyncService();
  189. $this->assertEquals(
  190. '+331 61 62 63 65',
  191. $syncService->getOrganizationPhone($organization)
  192. );
  193. }
  194. public function testGetOrganizationPhoneWithMobilePhone() {
  195. $organization = $this->getMockBuilder(Organization::class)->getMock();
  196. $contactPoint1 = $this->getMockBuilder(ContactPoint::class)->getMock();
  197. $contactPoint2 = $this->getMockBuilder(ContactPoint::class)->getMock();
  198. $contactPoint3 = $this->getMockBuilder(ContactPoint::class)->getMock();
  199. $contactPoint1->method('getContactType')->willReturn(ContactPointTypeEnum::OTHER()->getValue());
  200. $contactPoint2->method('getContactType')->willReturn(ContactPointTypeEnum::BILL()->getValue());
  201. $contactPoint3->method('getContactType')->willReturn(ContactPointTypeEnum::PRINCIPAL()->getValue());
  202. $contactPoint2->expects($this->once())->method('getTelphone')->willReturn(null);
  203. $contactPoint2->expects($this->once())->method('getMobilPhone')->willReturn('0661626365');
  204. $organization
  205. ->expects($this->once())
  206. ->method('getContactPoints')
  207. ->willReturn(
  208. [$contactPoint1, $contactPoint2, $contactPoint3]
  209. );
  210. $syncService = $this->newDolibarrSyncService();
  211. $this->assertEquals(
  212. '+336 61 62 63 65',
  213. $syncService->getOrganizationPhone($organization)
  214. );
  215. }
  216. public function testGetOrganizationPhoneWithNoPhone() {
  217. $organization = $this->getMockBuilder(Organization::class)->getMock();
  218. $organization
  219. ->expects($this->once())
  220. ->method('getContactPoints')
  221. ->willReturn([]);
  222. $syncService = $this->newDolibarrSyncService();
  223. $this->assertEquals(
  224. null,
  225. $syncService->getOrganizationPhone($organization)
  226. );
  227. }
  228. public function testGetOrganizationEmailWithExistingEmail() {
  229. $organization = $this->getMockBuilder(Organization::class)->getMock();
  230. $contactPoint1 = $this->getMockBuilder(ContactPoint::class)->getMock();
  231. $contactPoint2 = $this->getMockBuilder(ContactPoint::class)->getMock();
  232. $contactPoint3 = $this->getMockBuilder(ContactPoint::class)->getMock();
  233. $contactPoint1->method('getContactType')->willReturn(ContactPointTypeEnum::OTHER()->getValue());
  234. $contactPoint2->method('getContactType')->willReturn(ContactPointTypeEnum::BILL()->getValue());
  235. $contactPoint3->method('getContactType')->willReturn(ContactPointTypeEnum::PRINCIPAL()->getValue());
  236. $contactPoint2->method('getEmail')->willReturn('email@email.com');
  237. $organization
  238. ->expects($this->once())
  239. ->method('getContactPoints')
  240. ->willReturn(
  241. [$contactPoint1, $contactPoint2, $contactPoint3]
  242. );
  243. $syncService = $this->newDolibarrSyncService();
  244. $this->assertEquals(
  245. 'email@email.com',
  246. $syncService->getOrganizationEmail($organization)
  247. );
  248. }
  249. public function testGetOrganizationEmailWithNoEmail() {
  250. $organization = $this->getMockBuilder(Organization::class)->getMock();
  251. $organization
  252. ->expects($this->once())
  253. ->method('getContactPoints')
  254. ->willReturn([]);
  255. $syncService = $this->newDolibarrSyncService();
  256. $this->assertEquals(
  257. null,
  258. $syncService->getOrganizationEmail($organization)
  259. );
  260. }
  261. public function testCountWithMission() {
  262. $members = [
  263. 123 => [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::TEACHER()->getValue()],
  264. 124 => [FunctionEnum::TEACHER()->getValue()],
  265. 125 => [FunctionEnum::STUDENT()->getValue()],
  266. 126 => [FunctionEnum::TREASURER()->getValue()],
  267. ];
  268. $this->assertEquals(
  269. 2,
  270. TestableDolibarrSyncService::countWithMission([FunctionEnum::TEACHER()->getValue()], $members)
  271. );
  272. $this->assertEquals(
  273. 3,
  274. TestableDolibarrSyncService::countWithMission(
  275. [FunctionEnum::TEACHER()->getValue(), FunctionEnum::TREASURER()->getValue()],
  276. $members
  277. )
  278. );
  279. $this->assertEquals(
  280. 1,
  281. TestableDolibarrSyncService::countWithMission([FunctionEnum::STUDENT()->getValue()], $members)
  282. );
  283. $this->assertEquals(
  284. 0,
  285. TestableDolibarrSyncService::countWithMission([FunctionEnum::ARCHIVIST()->getValue()], $members)
  286. );
  287. }
  288. public function testGetPersonContact() {
  289. $person = $this->getMockBuilder(Person::class)->getMock();
  290. $contactPoint1 = $this->getMockBuilder(ContactPoint::class)->getMock();
  291. $contactPoint2 = $this->getMockBuilder(ContactPoint::class)->getMock();
  292. $contactPoint1->method('getContactType')->willReturn(ContactPointTypeEnum::OTHER()->getValue());
  293. $contactPoint2->method('getContactType')->willReturn(ContactPointTypeEnum::PRINCIPAL()->getValue());
  294. $person->expects($this->once())->method('getContactPoints')->willReturn([$contactPoint1, $contactPoint2]);
  295. $syncService = $this->newDolibarrSyncService();
  296. $this->assertEquals(
  297. $contactPoint2,
  298. $syncService->getPersonContact($person)
  299. );
  300. $person2 = $this->getMockBuilder(Person::class)->getMock();
  301. $person2->expects($this->once())->method('getContactPoints')->willReturn([]);
  302. $this->assertEquals(null, $syncService->getPersonContact($person2));
  303. }
  304. public function testFormatContactPosition() {
  305. $this->translator->method('trans')->will(
  306. $this->returnCallback(function($mission, $params) {
  307. if ($mission == FunctionEnum::PRESIDENT()) {
  308. if ($params === ['gender' => 'X']) { return 'Président(e)'; }
  309. elseif ($params === ['gender' => 'M']) { return 'Président'; }
  310. elseif ($params === ['gender' => 'F']) { return 'Présidente'; }
  311. } elseif ($mission == FunctionEnum::DIRECTOR()) {
  312. if ($params === ['gender' => 'X']) { return 'Directeur(ice)'; }
  313. elseif ($params === ['gender' => 'M']) { return 'Directeur'; }
  314. elseif ($params === ['gender' => 'F']) { return 'Directrice'; }
  315. }
  316. throw new \AssertionError('translator->trans stub has no matching call for arguments ' . json_encode([$mission, $params]));
  317. })
  318. );
  319. $syncService = $this->newDolibarrSyncService();
  320. $this->assertEquals(
  321. 'Président(e)',
  322. $syncService->formatContactPosition([FunctionEnum::PRESIDENT()->getValue()])
  323. );
  324. $this->assertEquals(
  325. 'Président',
  326. $syncService->formatContactPosition([FunctionEnum::PRESIDENT()->getValue()], 'MISTER')
  327. );
  328. $this->assertEquals(
  329. 'Présidente',
  330. $syncService->formatContactPosition([FunctionEnum::PRESIDENT()->getValue()], 'MISS')
  331. );
  332. $this->assertEquals(
  333. 'Présidente, Directrice',
  334. $syncService->formatContactPosition(
  335. [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::DIRECTOR()->getValue()],
  336. 'MISS'
  337. )
  338. );
  339. $this->assertEquals(
  340. 'Président, Directeur',
  341. $syncService->formatContactPosition(
  342. [FunctionEnum::PRESIDENT()->getValue(), FunctionEnum::DIRECTOR()->getValue(), FunctionEnum::ADHERENT()->getValue()],
  343. 'MISTER'
  344. )
  345. );
  346. }
  347. public function testFormatPhoneNumber() {
  348. $phoneNumber = new PhoneNumber();
  349. $phoneNumber->setCountryCode(33);
  350. $phoneNumber->setNationalNumber('1 02 03 04 05');
  351. $this->assertEquals(
  352. '+33 1 02 03 04 05',
  353. TestableDolibarrSyncService::formatPhoneNumber($phoneNumber)
  354. );
  355. }
  356. public function testFilterDiff() {
  357. $this->assertEquals(
  358. ['b' => -2, 'c' => ['e' => ['f' => -5]], 'g' => 7],
  359. TestableDolibarrSyncService::filterDiff(
  360. ['a' => 1, 'b' => 2, 'c' => ['d' => 4, 'e' => ['f' => 5]]],
  361. ['a' => 1, 'b' => -2, 'c' => ['d' => 4, 'e' => ['f' => -5]], 'g' => 7],
  362. )
  363. );
  364. $this->assertEquals(
  365. [],
  366. TestableDolibarrSyncService::filterDiff(
  367. ['a' => 1, 'b' => 2, 'c' => ['d' => 4, 'e' => ['f' => 5]]],
  368. ['a' => 1, 'b' => 2, 'c' => ['d' => 4, 'e' => ['f' => 5]]],
  369. )
  370. );
  371. $this->assertEquals(
  372. [],
  373. TestableDolibarrSyncService::filterDiff(
  374. [],
  375. [],
  376. )
  377. );
  378. $this->assertEquals(
  379. ['a' => 1],
  380. TestableDolibarrSyncService::filterDiff(
  381. [],
  382. ['a' => 1],
  383. )
  384. );
  385. }
  386. }