phoneNumberUtil = $phoneNumberUtil; } public function interruptIfOrganizationExists(OrganizationCreationRequest $organizationCreationRequest): void { parent::interruptIfOrganizationExists($organizationCreationRequest); } public function validateSubdomain(string $subdomainValue): void { parent::validateSubdomain($subdomainValue); } public function makeOrganizationWithRelations( OrganizationCreationRequest $organizationCreationRequest, ): Organization { return parent::makeOrganizationWithRelations($organizationCreationRequest); } public function makeOrganization(OrganizationCreationRequest $organizationCreationRequest): Organization { return parent::makeOrganization($organizationCreationRequest); } public function makeParameters(OrganizationCreationRequest $organizationCreationRequest): Parameters { return parent::makeParameters($organizationCreationRequest); } public function makeSettings(OrganizationCreationRequest $organizationCreationRequest): Settings { return parent::makeSettings($organizationCreationRequest); } public function makePostalAddress(OrganizationCreationRequest $organizationCreationRequest): OrganizationAddressPostal { return parent::makePostalAddress($organizationCreationRequest); } public function makeContactPoint(OrganizationCreationRequest $organizationCreationRequest): ContactPoint { return parent::makeContactPoint($organizationCreationRequest); } public function makeNetworkOrganization(OrganizationCreationRequest $organizationCreationRequest): NetworkOrganization { return parent::makeNetworkOrganization($organizationCreationRequest); } public function makeAdminAccess(OrganizationCreationRequest $organizationCreationRequest): Access { return parent::makeAdminAccess($organizationCreationRequest); } public function makeCycles(): array { return parent::makeCycles(); } public function makeAccess(int|OrganizationMemberCreationRequest $creationRequestData, FunctionEnum $function, \DateTime $creationDate, ?int $authorId): Access { return parent::makeAccess($creationRequestData, $function, $creationDate, $authorId); } public function makePersonPostalAddress(OrganizationMemberCreationRequest $organizationMemberCreationRequest, \DateTime $creationDate, ?int $authorId): PersonAddressPostal { return parent::makePersonPostalAddress($organizationMemberCreationRequest, $creationDate, $authorId); } public function makePersonContactPoint(OrganizationMemberCreationRequest $organizationMemberCreationRequest, \DateTime $creationDate, ?int $authorId): ContactPoint { return parent::makePersonContactPoint($organizationMemberCreationRequest, $creationDate, $authorId); } public function makeSubdomain(OrganizationCreationRequest $organizationCreationRequest): Subdomain { return parent::makeSubdomain($organizationCreationRequest); } public function createTypo3Website(Organization $organization): ?int { return parent::createTypo3Website($organization); } public function updateAdminassosDb(Organization $organization): void { parent::updateAdminassosDb($organization); } public function normalizeIdentificationField(string $value): string { return parent::normalizeIdentificationField($value); } public function deleteTypo3Website(int $organizationId): void { parent::deleteTypo3Website($organizationId); } public function switchDolibarrSocietyToProspect(int $organizationId): void { parent::switchDolibarrSocietyToProspect($organizationId); } public function getFutureOrphanPersons(Organization $organization): array { return parent::getFutureOrphanPersons($organization); } } class OrganizationFactoryTest extends TestCase { private readonly MockObject|SubdomainService $subdomainService; private readonly MockObject|OrganizationRepository $organizationRepository; private readonly MockObject|CountryRepository $countryRepository; private readonly MockObject|OrganizationUtils $organizationUtils; private readonly MockObject|Typo3Service $typo3Service; private readonly MockObject|DolibarrApiService $dolibarrApiService; private readonly MockObject|EntityManagerInterface $entityManager; private readonly MockObject|PersonRepository $personRepository; private readonly MockObject|BindFileService $bindFileService; private readonly MockObject|LoggerInterface $logger; private readonly MockObject|OrganizationIdentificationRepository $organizationIdentificationRepository; private readonly MockObject|ApiLegacyRequestService $apiLegacyRequestService; private readonly MockObject|PhoneNumberUtil $phoneNumberUtil; private readonly MockObject|FunctionTypeRepository $functionTypeRepository; private readonly MockObject|\App\Repository\Access\AccessRepository $accessRepository; public function setUp(): void { $this->subdomainService = $this->getMockBuilder(SubdomainService::class)->disableOriginalConstructor()->getMock(); $this->organizationRepository = $this->getMockBuilder(OrganizationRepository::class)->disableOriginalConstructor()->getMock(); $this->countryRepository = $this->getMockBuilder(CountryRepository::class)->disableOriginalConstructor()->getMock(); $this->organizationUtils = $this->getMockBuilder(OrganizationUtils::class)->disableOriginalConstructor()->getMock(); $this->typo3Service = $this->getMockBuilder(Typo3Service::class)->disableOriginalConstructor()->getMock(); $this->dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)->disableOriginalConstructor()->getMock(); $this->entityManager = $this->getMockBuilder(EntityManagerInterface::class)->disableOriginalConstructor()->getMock(); $this->personRepository = $this->getMockBuilder(PersonRepository::class)->disableOriginalConstructor()->getMock(); $this->bindFileService = $this->getMockBuilder(BindFileService::class)->disableOriginalConstructor()->getMock(); $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(); $this->functionTypeRepository = $this->getMockBuilder(FunctionTypeRepository::class)->disableOriginalConstructor()->getMock(); $this->fileManager = $this->getMockBuilder(FileManager::class)->disableOriginalConstructor()->getMock(); $this->accessRepository = $this->getMockBuilder(\App\Repository\Access\AccessRepository::class)->disableOriginalConstructor()->getMock(); } public function tearDown(): void { DatesUtils::clearFakeDatetime(); } private function getOrganizationFactoryMockFor(string $methodName): TestableOrganizationFactory|MockObject { $organizationFactory = $this ->getMockBuilder(TestableOrganizationFactory::class) ->setConstructorArgs( [ $this->subdomainService, $this->organizationRepository, $this->countryRepository, $this->organizationUtils, $this->typo3Service, $this->dolibarrApiService, $this->entityManager, $this->personRepository, $this->bindFileService, $this->organizationIdentificationRepository, $this->apiLegacyRequestService, $this->functionTypeRepository, $this->fileManager, $this->accessRepository, ]) ->setMethodsExcept(['setLoggerInterface', 'setPhoneNumberUtil', $methodName]) ->getMock(); $organizationFactory->setLoggerInterface($this->logger); $organizationFactory->setPhoneNumberUtil($this->phoneNumberUtil); return $organizationFactory; } public function testCreate(): 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(false); $organizationCreationRequest->method('getCreateWebsite')->willReturn(true); $this->entityManager->expects(self::once())->method('beginTransaction'); $organizationFactory->expects(self::once())->method('interruptIfOrganizationExists'); $organizationFactory->expects(self::once())->method('validateSubdomain')->with('subdomain'); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organizationFactory ->expects(self::once()) ->method('makeOrganizationWithRelations') ->with($organizationCreationRequest) ->willReturn($organization); $this->entityManager->expects(self::once())->method('persist')->with($organization); $this->entityManager->expects(self::once())->method('flush'); $this->entityManager->expects(self::once())->method('commit'); $this->dolibarrApiService ->expects(self::once()) ->method('createSociety') ->with($organization, false) ->willReturn(456); $this->bindFileService ->expects(self::once()) ->method('registerSubdomain') ->with('subdomain'); $organizationFactory ->expects(self::once()) ->method('createTypo3Website') ->with($organization) ->willReturn(789); $this->logger ->method('info') ->withConsecutive( ["Start the creation of a new organization named 'foo'"], ["Subdomain is valid and available : 'subdomain'"], ['Organization created with all its relations'], ['Organization persisted in the DB'], ['New dolibarr structure created (uid : 456)'], ['Subdomain registered'], ['Typo3 website created (root uid: 789)'], ['Adminassos db updated'] ); $organizationCreationRequest ->expects(self::once()) ->method('setStatus') ->with(OrganizationCreationRequest::STATUS_OK); $result = $organizationFactory->create($organizationCreationRequest); $this->assertEquals( $organization, $result ); } public function testCreateWithRollback(): 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(false); $organizationCreationRequest->method('getCreateWebsite')->willReturn(true); $this->entityManager->expects(self::once())->method('beginTransaction'); $organizationFactory->expects(self::once())->method('interruptIfOrganizationExists'); $organizationFactory->expects(self::once())->method('validateSubdomain')->with('subdomain'); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organizationFactory ->expects(self::once()) ->method('makeOrganizationWithRelations') ->with($organizationCreationRequest) ->willReturn($organization); $this->entityManager->expects(self::once())->method('persist')->with($organization); $this->entityManager->expects(self::once())->method('flush')->willThrowException(new \RuntimeException('some error')); $this->entityManager->expects(self::once())->method('rollback'); $this->dolibarrApiService ->expects(self::never()) ->method('createSociety'); $this->bindFileService ->expects(self::never()) ->method('registerSubdomain'); $organizationFactory ->expects(self::never()) ->method('createTypo3Website'); $this->logger ->method('info') ->withConsecutive( ["Start the creation of a new organization named 'foo'"], ["Subdomain is valid and available : 'subdomain'"], ['Organization created with all its relations'] ); $this->logger ->method('critical') ->with( $this->matchesRegularExpression('/^An error happened, operation cancelled\nRuntimeException: some error.*/') ); $this->expectException(\RuntimeException::class); $result = $organizationFactory->create($organizationCreationRequest); } public function testCreateWithExistingOrganization(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('create'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getName')->willReturn('foo'); $this->entityManager->expects(self::once())->method('beginTransaction'); $organizationFactory->expects(self::once())->method('interruptIfOrganizationExists')->willThrowException(new \RuntimeException('An organization named foo already exists')); $organizationFactory->expects(self::never())->method('validateSubdomain'); $organizationFactory ->expects(self::never()) ->method('makeOrganizationWithRelations'); $this->entityManager->expects(self::never())->method('persist'); $this->entityManager->expects(self::never())->method('flush'); $this->entityManager->expects(self::once())->method('rollback'); $this->dolibarrApiService ->expects(self::never()) ->method('createSociety'); $this->bindFileService ->expects(self::never()) ->method('registerSubdomain'); $organizationFactory ->expects(self::never()) ->method('createTypo3Website'); $this->logger ->method('info') ->withConsecutive( ["Start the creation of a new organization named 'foo'"], ); $this->logger ->method('critical') ->with( $this->matchesRegularExpression("/^An error happened, operation cancelled\nRuntimeException: An organization named foo already exists.*/") ); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('An organization named foo already exists'); $result = $organizationFactory->create($organizationCreationRequest); } public function testCreateNoWebsiteAndIsClient(): 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(false); $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) ->willReturn(456); $organizationFactory ->expects(self::never()) ->method('createTypo3Website'); $this->logger ->expects(self::once()) ->method('warning') ->with('Typo3 website creation was not required'); $result = $organizationFactory->create($organizationCreationRequest); $this->assertEquals( $organization, $result ); } 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'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getName')->willReturn('foo'); $organizationCreationRequest->method('getSiretNumber')->willReturn(''); $organizationCreationRequest->method('getWaldecNumber')->willReturn(''); $organizationCreationRequest->method('getIdentifier')->willReturn(''); $organizationCreationRequest->method('getStreetAddress1')->willReturn('part1'); $organizationCreationRequest->method('getStreetAddress2')->willReturn('part2'); $organizationCreationRequest->method('getStreetAddress3')->willReturn('part3'); $organizationCreationRequest->method('getCity')->willReturn('Paris'); $organizationCreationRequest->method('getPostalCode')->willReturn('75000'); $this->organizationIdentificationRepository ->expects(self::exactly(2)) ->method('findOneBy') ->willReturn(null); $organizationFactory ->method('normalizeIdentificationField') ->willReturnMap([ ['foo', 'foo'], ['part1 part2 part3', 'part1 part2 part3'], ]); $organizationFactory->interruptIfOrganizationExists($organizationCreationRequest); } public function testInterruptIfOrganizationExistsNotExistingNonExistingWithIdentifiers(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('interruptIfOrganizationExists'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getName')->willReturn('foo'); $organizationCreationRequest->method('getSiretNumber')->willReturn('123456'); $organizationCreationRequest->method('getWaldecNumber')->willReturn('W123456'); $organizationCreationRequest->method('getIdentifier')->willReturn('FR000000000000'); $organizationCreationRequest->method('getStreetAddress1')->willReturn('part1'); $organizationCreationRequest->method('getStreetAddress2')->willReturn('part2'); $organizationCreationRequest->method('getStreetAddress3')->willReturn('part3'); $organizationCreationRequest->method('getCity')->willReturn('Paris'); $organizationCreationRequest->method('getPostalCode')->willReturn('75000'); $organizationFactory ->method('normalizeIdentificationField') ->willReturnMap([ ['foo', 'foo'], ['part1 part2 part3', 'part1 part2 part3'], ]); $this->organizationIdentificationRepository ->expects(self::exactly(5)) ->method('findOneBy') ->willReturnMap([ [['siretNumber' => '123456'], null, null], [['waldecNumber' => 'W123456'], null, null], [['identifier' => 'FR000000000000'], null, null], [['normalizedName' => 'foo', 'addressCity' => 'Paris'], null, null], [['normalizedAddress' => 'part1 part2 part3', 'addressCity' => 'Paris', 'postalCode' => '75000'], null, null], ]); $organizationFactory->interruptIfOrganizationExists($organizationCreationRequest); } public function testInterruptIfOrganizationExistsExistingWithSiret(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('interruptIfOrganizationExists'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getName')->willReturn('foo'); $organizationCreationRequest->method('getSiretNumber')->willReturn('123456'); $organizationCreationRequest->method('getWaldecNumber')->willReturn('W123456'); $organizationCreationRequest->method('getIdentifier')->willReturn('FR000000000000'); $organizationCreationRequest->method('getStreetAddress1')->willReturn('part1'); $organizationCreationRequest->method('getStreetAddress2')->willReturn('part2'); $organizationCreationRequest->method('getStreetAddress3')->willReturn('part3'); $organizationCreationRequest->method('getCity')->willReturn('Paris'); $organizationCreationRequest->method('getPostalCode')->willReturn('75000'); $organizationFactory ->method('normalizeIdentificationField') ->willReturnMap([ ['foo', 'foo'], ['part1 part2 part3', 'part1 part2 part3'], ]); $organization = $this->getMockBuilder(Organization::class)->getMock(); $this->organizationIdentificationRepository ->method('findOneBy') ->willReturnMap([ [['siretNumber' => '123456'], null, $organization], [['waldecNumber' => 'W123456'], null, null], [['identifier' => 'FR000000000000'], null, null], [['normalizedName' => 'foo', 'addressCity' => 'Paris'], null, null], [['normalizedAddress' => 'part1 part2 part3', 'addressCity' => 'Paris', 'postalCode' => '75000'], null, null], ]); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage("This siret number is already registered : '123456'"); $organizationFactory->interruptIfOrganizationExists($organizationCreationRequest); } public function testInterruptIfOrganizationExistsExistingWithWaldec(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('interruptIfOrganizationExists'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getName')->willReturn('foo'); $organizationCreationRequest->method('getSiretNumber')->willReturn('123456'); $organizationCreationRequest->method('getWaldecNumber')->willReturn('W123456'); $organizationCreationRequest->method('getIdentifier')->willReturn('FR000000000000'); $organizationCreationRequest->method('getStreetAddress1')->willReturn('part1'); $organizationCreationRequest->method('getStreetAddress2')->willReturn('part2'); $organizationCreationRequest->method('getStreetAddress3')->willReturn('part3'); $organizationCreationRequest->method('getCity')->willReturn('Paris'); $organizationCreationRequest->method('getPostalCode')->willReturn('75000'); $organizationFactory ->method('normalizeIdentificationField') ->willReturnMap([ ['foo', 'foo'], ['part1 part2 part3', 'part1 part2 part3'], ]); $organization = $this->getMockBuilder(Organization::class)->getMock(); $this->organizationIdentificationRepository ->method('findOneBy') ->willReturnMap([ [['siretNumber' => '123456'], null, null], [['waldecNumber' => 'W123456'], null, $organization], [['identifier' => 'FR000000000000'], null, null], [['normalizedName' => 'foo', 'addressCity' => 'Paris'], null, null], [['normalizedAddress' => 'part1 part2 part3', 'addressCity' => 'Paris', 'postalCode' => '75000'], null, null], ]); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage("This RNA identifier (waldec number) is already registered : 'W123456'"); $organizationFactory->interruptIfOrganizationExists($organizationCreationRequest); } public function testInterruptIfOrganizationExistsExistingWithCMFIdentifier(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('interruptIfOrganizationExists'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getName')->willReturn('foo'); $organizationCreationRequest->method('getSiretNumber')->willReturn('123456'); $organizationCreationRequest->method('getWaldecNumber')->willReturn('W123456'); $organizationCreationRequest->method('getIdentifier')->willReturn('FR000000000000'); $organizationCreationRequest->method('getStreetAddress1')->willReturn('part1'); $organizationCreationRequest->method('getStreetAddress2')->willReturn('part2'); $organizationCreationRequest->method('getStreetAddress3')->willReturn('part3'); $organizationCreationRequest->method('getCity')->willReturn('Paris'); $organizationCreationRequest->method('getPostalCode')->willReturn('75000'); $organizationFactory ->method('normalizeIdentificationField') ->willReturnMap([ ['foo', 'foo'], ['part1 part2 part3', 'part1 part2 part3'], ]); $organization = $this->getMockBuilder(Organization::class)->getMock(); $this->organizationIdentificationRepository ->method('findOneBy') ->willReturnMap([ [['siretNumber' => '123456'], null, null], [['waldecNumber' => 'W123456'], null, null], [['identifier' => 'FR000000000000'], null, $organization], [['normalizedName' => 'foo', 'addressCity' => 'Paris'], null, null], [['normalizedAddress' => 'part1 part2 part3', 'addressCity' => 'Paris', 'postalCode' => '75000'], null, null], ]); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage("This CMF identifier is already registered : 'FR000000000000'"); $organizationFactory->interruptIfOrganizationExists($organizationCreationRequest); } public function testInterruptIfOrganizationExistsExistingWithSameNameAndCity(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('interruptIfOrganizationExists'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getName')->willReturn('foo'); $organizationCreationRequest->method('getSiretNumber')->willReturn('123456'); $organizationCreationRequest->method('getWaldecNumber')->willReturn('W123456'); $organizationCreationRequest->method('getIdentifier')->willReturn('FR000000000000'); $organizationCreationRequest->method('getStreetAddress1')->willReturn('part1'); $organizationCreationRequest->method('getStreetAddress2')->willReturn('part2'); $organizationCreationRequest->method('getStreetAddress3')->willReturn('part3'); $organizationCreationRequest->method('getCity')->willReturn('Paris'); $organizationCreationRequest->method('getPostalCode')->willReturn('75000'); $organizationFactory ->method('normalizeIdentificationField') ->willReturnMap([ ['foo', 'foo'], ['part1 part2 part3', 'part1 part2 part3'], ]); $organization = $this->getMockBuilder(Organization::class)->getMock(); $this->organizationIdentificationRepository ->method('findOneBy') ->willReturnMap([ [['siretNumber' => '123456'], null, null], [['waldecNumber' => 'W123456'], null, null], [['identifier' => 'FR000000000000'], null, null], [['normalizedName' => 'foo', 'addressCity' => 'Paris'], null, $organization], [['normalizedAddress' => 'part1 part2 part3', 'addressCity' => 'Paris', 'postalCode' => '75000'], null, null], ]); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage("An organization named 'foo' already exists in Paris"); $organizationFactory->interruptIfOrganizationExists($organizationCreationRequest); } public function testInterruptIfOrganizationExistsExistingWithSameAddress(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('interruptIfOrganizationExists'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getName')->willReturn('foo'); $organizationCreationRequest->method('getSiretNumber')->willReturn('123456'); $organizationCreationRequest->method('getWaldecNumber')->willReturn('W123456'); $organizationCreationRequest->method('getIdentifier')->willReturn('FR000000000000'); $organizationCreationRequest->method('getStreetAddress1')->willReturn('part1'); $organizationCreationRequest->method('getStreetAddress2')->willReturn('part2'); $organizationCreationRequest->method('getStreetAddress3')->willReturn('part3'); $organizationCreationRequest->method('getCity')->willReturn('Paris'); $organizationCreationRequest->method('getPostalCode')->willReturn('75000'); $organizationFactory ->method('normalizeIdentificationField') ->willReturnMap([ ['foo', 'foo'], ['part1 part2 part3', 'part1 part2 part3'], ]); $organization = $this->getMockBuilder(Organization::class)->getMock(); $this->organizationIdentificationRepository ->method('findOneBy') ->willReturnMap([ [['siretNumber' => '123456'], null, null], [['waldecNumber' => 'W123456'], null, null], [['identifier' => 'FR000000000000'], null, null], [['normalizedName' => 'foo', 'addressCity' => 'Paris'], null, null], [['normalizedAddress' => 'part1 part2 part3', 'addressCity' => 'Paris', 'postalCode' => '75000'], null, $organization], ]); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('An organization already exists at this address.'); $organizationFactory->interruptIfOrganizationExists($organizationCreationRequest); } public function testValidateSubdomain(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('validateSubdomain'); $this->subdomainService->expects(self::once())->method('isValidSubdomain')->willReturn(true); $this->subdomainService->expects(self::once())->method('isReservedSubdomain')->willReturn(false); $this->subdomainService->expects(self::once())->method('isRegistered')->willReturn(false); $organizationFactory->validateSubdomain('foo'); } public function testValidateSubdomainIsNotValid(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('validateSubdomain'); $this->subdomainService->method('isValidSubdomain')->willReturn(false); $this->subdomainService->method('isReservedSubdomain')->willReturn(false); $this->subdomainService->method('isRegistered')->willReturn(false); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('Not a valid subdomain : foo'); $organizationFactory->validateSubdomain('foo'); } public function testValidateSubdomainIsReserved(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('validateSubdomain'); $this->subdomainService->method('isValidSubdomain')->willReturn(true); $this->subdomainService->method('isReservedSubdomain')->willReturn(true); $this->subdomainService->method('isRegistered')->willReturn(false); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('This subdomain is not available : foo'); $organizationFactory->validateSubdomain('foo'); } public function testValidateSubdomainIsRegistered(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('validateSubdomain'); $this->subdomainService->method('isValidSubdomain')->willReturn(true); $this->subdomainService->method('isReservedSubdomain')->willReturn(false); $this->subdomainService->method('isRegistered')->willReturn(true); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('This subdomain is already registered : foo'); $organizationFactory->validateSubdomain('foo'); } public function testMakeOrganizationWithRelations(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeOrganizationWithRelations'); $creationDate = $this->getMockBuilder(\DateTime::class)->getMock(); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getCreationDate')->willReturn($creationDate); $organizationCreationRequest->method('getAuthorId')->willReturn(1); $organization = $this->getMockBuilder(Organization::class)->getMock(); // Création de l'organisation $organizationFactory ->expects(self::once()) ->method('makeOrganization') ->with($organizationCreationRequest) ->willReturn($organization); // Création des Parameters $parameters = $this->getMockBuilder(Parameters::class)->getMock(); $organizationFactory ->expects(self::once()) ->method('makeParameters') ->with($organizationCreationRequest) ->willReturn($parameters); $organization->expects(self::once())->method('setParameters')->with($parameters); // Création des Settings $settings = $this->getMockBuilder(Settings::class)->getMock(); $organizationFactory ->expects(self::once()) ->method('makeSettings') ->with($organizationCreationRequest) ->willReturn($settings); $organization->expects(self::once())->method('setSettings')->with($settings); // Création de l'adresse postale $organizationAddressPostal = $this->getMockBuilder(OrganizationAddressPostal::class)->getMock(); $organizationFactory ->expects(self::once()) ->method('makePostalAddress') ->with($organizationCreationRequest) ->willReturn($organizationAddressPostal); $organization->expects(self::once())->method('addOrganizationAddressPostal')->with($organizationAddressPostal); // Création du point de contact $contactPoint = $this->getMockBuilder(ContactPoint::class)->getMock(); $organizationFactory ->expects(self::once()) ->method('makeContactPoint') ->with($organizationCreationRequest) ->willReturn($contactPoint); $organization->expects(self::once())->method('addContactPoint')->with($contactPoint); // Rattachement au réseau $networkOrganization = $this->getMockBuilder(NetworkOrganization::class)->getMock(); $organizationFactory ->expects(self::once()) ->method('makeNetworkOrganization') ->with($organizationCreationRequest) ->willReturn($networkOrganization); $organization->expects(self::once())->method('addNetworkOrganization')->with($networkOrganization); // Créé l'admin $adminAccess = $this->getMockBuilder(Access::class)->getMock(); $organizationFactory ->expects(self::once()) ->method('makeAdminAccess') ->with($organizationCreationRequest) ->willReturn($adminAccess); // Le `$organization->expects(...)->method('addAccess')` est implémenté plus loin, // après la création du président et du directeur. // Création des cycles $cycle1 = $this->getMockBuilder(Cycle::class)->getMock(); $cycle2 = $this->getMockBuilder(Cycle::class)->getMock(); $cycle3 = $this->getMockBuilder(Cycle::class)->getMock(); $organizationFactory ->expects(self::once()) ->method('makeCycles') ->willReturn([$cycle1, $cycle2, $cycle3]); $organization->expects(self::exactly(3))->method('addCycle')->withConsecutive([$cycle1], [$cycle2], [$cycle3]); // Création du président et du directeur $organizationMemberCreationRequest1 = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock(); $organizationCreationRequest->method('getPresident')->willReturn($organizationMemberCreationRequest1); $organizationMemberCreationRequest2 = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock(); $organizationCreationRequest->method('getDirector')->willReturn($organizationMemberCreationRequest2); $access1 = $this->getMockBuilder(Access::class)->getMock(); $access2 = $this->getMockBuilder(Access::class)->getMock(); $organizationFactory ->expects(self::exactly(2)) ->method('makeAccess') ->willReturnMap([ [$organizationMemberCreationRequest1, FunctionEnum::PRESIDENT, $creationDate, 1, $access1], [$organizationMemberCreationRequest2, FunctionEnum::DIRECTOR, $creationDate, 1, $access2], ]); $organization ->expects(self::exactly(3)) ->method('addAccess') ->withConsecutive([$adminAccess], [$access1], [$access2]); // Création du sous-domaine $subdomain = $this->getMockBuilder(Subdomain::class)->getMock(); $organizationFactory ->expects(self::once()) ->method('makeSubdomain') ->with($organizationCreationRequest) ->willReturn($subdomain); $organization->expects(self::once())->method('addSubdomain')->with($subdomain); // Enregistrement du sous domaine dans Parameters (retrocompatibilité v1) $organization->method('getParameters')->willReturn($parameters); $organizationCreationRequest->method('getSubdomain')->willReturn('foo'); $parameters->expects(self::once())->method('setSubDomain')->with('foo'); $parameters->expects(self::once())->method('setOtherWebsite')->with('https://foo.opentalent.fr'); $result = $organizationFactory->makeOrganizationWithRelations($organizationCreationRequest); $this->assertEquals( $result, $organization ); } public function testMakeOrganizationWithRelationsNoPresidentNoDirector(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeOrganizationWithRelations'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organization = $this->getMockBuilder(Organization::class)->getMock(); // Création de l'organisation $organizationFactory ->expects(self::once()) ->method('makeOrganization') ->with($organizationCreationRequest) ->willReturn($organization); $organizationCreationRequest->method('getPresident')->willReturn(null); $organizationCreationRequest->method('getDirector')->willReturn(null); // Un seul appel, pour l'adminAccess $organization ->expects(self::once()) ->method('addAccess'); $organizationFactory->makeOrganizationWithRelations($organizationCreationRequest); } public function testMakeOrganization(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeOrganization'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getName')->willReturn('My Organization'); $organizationCreationRequest->method('getLegalStatus')->willReturn(LegalEnum::ASSOCIATION_LAW_1901); $organizationCreationRequest->method('getPrincipalType')->willReturn(PrincipalTypeEnum::ARTISTIC_EDUCATION_ONLY); $organization = $organizationFactory->makeOrganization($organizationCreationRequest); $this->assertEquals( 'My Organization', $organization->getName() ); $this->assertEquals( LegalEnum::ASSOCIATION_LAW_1901, $organization->getLegalStatus() ); $this->assertEquals( PrincipalTypeEnum::ARTISTIC_EDUCATION_ONLY, $organization->getPrincipalType() ); } public function testMakeParameters(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeParameters'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $parameters = $organizationFactory->makeParameters($organizationCreationRequest); $this->assertInstanceOf(Parameters::class, $parameters); } public function testMakeSettings(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeSettings'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getProduct')->willReturn(SettingsProductEnum::ARTIST_PREMIUM); $settings = $organizationFactory->makeSettings($organizationCreationRequest); $this->assertEquals( SettingsProductEnum::ARTIST_PREMIUM, $settings->getProduct() ); } public function testMakePostalAddress(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makePostalAddress'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getStreetAddress1')->willReturn('address1'); $organizationCreationRequest->method('getStreetAddress2')->willReturn('address2'); $organizationCreationRequest->method('getStreetAddress3')->willReturn('address3'); $organizationCreationRequest->method('getPostalCode')->willReturn('00000'); $organizationCreationRequest->method('getCity')->willReturn('city'); $organizationCreationRequest->method('getCountryId')->willReturn(1); $country = $this->getMockBuilder(Country::class)->getMock(); $this->countryRepository->expects(self::once())->method('find')->with(1)->willReturn($country); $organizationAddressPostal = $organizationFactory->makePostalAddress($organizationCreationRequest); $this->assertEquals( AddressPostalOrganizationTypeEnum::ADDRESS_HEAD_OFFICE, $organizationAddressPostal->getType() ); $addressPostal = $organizationAddressPostal->getAddressPostal(); $this->assertEquals( 'address1', $addressPostal->getStreetAddress() ); $this->assertEquals( 'address2', $addressPostal->getStreetAddressSecond() ); $this->assertEquals( 'address3', $addressPostal->getStreetAddressThird() ); $this->assertEquals( '00000', $addressPostal->getPostalCode() ); $this->assertEquals( 'city', $addressPostal->getAddressCity() ); $this->assertEquals( $country, $addressPostal->getAddressCountry() ); } public function testMakePostalAddressNonExistingCountry(): 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'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $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( 'contact@domain.net', $contactPoint->getEmail() ); $this->assertEquals( $phoneNumber, $contactPoint->getTelphone() ); } 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 { $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::MANAGER); $parent->method('getSettings')->willReturn($settings); $this->organizationRepository->expects(self::once())->method('find')->with(123)->willReturn($parent); $network = $this->getMockBuilder(Network::class)->getMock(); $networkOrganization = $this->getMockBuilder(NetworkOrganization::class)->getMock(); $networkOrganization->method('getNetwork')->willReturn($network); $this->organizationUtils ->expects(self::once()) ->method('getActiveNetworkOrganization') ->with($parent) ->willReturn($networkOrganization); $networkOrganization = $organizationFactory->makeNetworkOrganization($organizationCreationRequest); $this->assertEquals( $parent, $networkOrganization->getParent() ); $this->assertEquals( $network, $networkOrganization->getNetwork() ); $this->assertEquals( '2024-01-01', $networkOrganization->getStartDate()->format('Y-m-d') ); } public function testMakeNetworkOrganizationMissingParent(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeNetworkOrganization'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getParentId')->willReturn(123); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('No parent organization found for id 123'); $this->organizationRepository->expects(self::once())->method('find')->with(123)->willReturn(null); $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'); $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::MANAGER); $parent->method('getSettings')->willReturn($settings); $this->organizationRepository->expects(self::once())->method('find')->with(123)->willReturn($parent); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('No network found for parent 123'); $this->organizationRepository->expects(self::once())->method('find')->with(123)->willReturn($parent); $organizationFactory->makeNetworkOrganization($organizationCreationRequest); } public function testMakeNetworkOrganizationIsCMFInvalidIdentifier(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeNetworkOrganization'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getParentId')->willReturn(123); $organizationCreationRequest->method('getIdentifier')->willReturn('invalid'); $parent = $this->getMockBuilder(Organization::class)->getMock(); $settings = $this->getMockBuilder(Settings::class)->getMock(); $settings->method('getProduct')->willReturn(SettingsProductEnum::MANAGER); $parent->method('getSettings')->willReturn($settings); $this->organizationRepository->method('find')->with(123)->willReturn($parent); $network = $this->getMockBuilder(Network::class)->getMock(); $network->method('getId')->willReturn(NetworkEnum::CMF->value); $networkOrganization = $this->getMockBuilder(NetworkOrganization::class)->getMock(); $networkOrganization->method('getNetwork')->willReturn($network); $this->organizationUtils ->method('getActiveNetworkOrganization') ->with($parent) ->willReturn($networkOrganization); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('CMF identifier is missing or invalid.'); $organizationFactory->makeNetworkOrganization($organizationCreationRequest); } public function testMakeNetworkOrganizationIsNotCMFInvalidIdentifier(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeNetworkOrganization'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getParentId')->willReturn(123); $organizationCreationRequest->method('getIdentifier')->willReturn('invalid'); $parent = $this->getMockBuilder(Organization::class)->getMock(); $settings = $this->getMockBuilder(Settings::class)->getMock(); $settings->method('getProduct')->willReturn(SettingsProductEnum::MANAGER); $parent->method('getSettings')->willReturn($settings); $this->organizationRepository->method('find')->with(123)->willReturn($parent); $network = $this->getMockBuilder(Network::class)->getMock(); $network->method('getId')->willReturn(NetworkEnum::OUTOFNET->value); $networkOrganization = $this->getMockBuilder(NetworkOrganization::class)->getMock(); $networkOrganization->method('getNetwork')->willReturn($network); $this->organizationUtils ->method('getActiveNetworkOrganization') ->with($parent) ->willReturn($networkOrganization); $result = $organizationFactory->makeNetworkOrganization($organizationCreationRequest); $this->assertEquals( $network, $result->getNetwork() ); } public function testMakeAdminAccess(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeAdminAccess'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getSubdomain')->willReturn('foo'); $adminAccess = $organizationFactory->makeAdminAccess($organizationCreationRequest); $this->assertTrue( $adminAccess->getAdminAccess() ); $this->assertEquals( 'adminfoo', $adminAccess->getPerson()->getUsername() ); $this->assertEquals( 32, strlen($adminAccess->getPerson()->getPassword()) ); } public function testMakeCycles(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeCycles'); $cycles = $organizationFactory->makeCycles(); $cyclesExpectedData = [ ['Cycle initiation', 10, CycleEnum::INITIATION_CYCLE], ['Cycle 1', 20, CycleEnum::CYCLE_1], ['Cycle 2', 30, CycleEnum::CYCLE_2], ['Cycle 3', 40, CycleEnum::CYCLE_3], ['Cycle 4', 50, CycleEnum::CYCLE_4], ['Hors cycle', 60, CycleEnum::OUT_CYCLE], ]; $i = 0; foreach ($cycles as $cycle) { $this->assertEquals( $cyclesExpectedData[$i][0], $cycle->getLabel() ); $this->assertEquals( $cyclesExpectedData[$i][1], $cycle->getOrder() ); $this->assertEquals( $cyclesExpectedData[$i][2], $cycle->getCycleEnum() ); $this->assertFalse( $cycle->getIsSystem() ); ++$i; } } public function testMakeAccessNewPerson(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeAccess'); $organizationMemberCreationRequest = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock(); $organizationMemberCreationRequest->method('getUsername')->willReturn('bob'); $organizationMemberCreationRequest->method('getName')->willReturn('Bob'); $organizationMemberCreationRequest->method('getGivenName')->willReturn('bOBBy'); $organizationMemberCreationRequest->method('getGender')->willReturn(GenderEnum::MISTER); $this->personRepository ->method('findOneBy') ->with(['username' => 'bob'], null) ->willReturn(null); $personAddressPostal = $this->getMockBuilder(PersonAddressPostal::class)->getMock(); $organizationFactory ->expects(self::once()) ->method('makePersonPostalAddress') ->with($organizationMemberCreationRequest) ->willReturn($personAddressPostal); $contactPoint = $this->getMockBuilder(ContactPoint::class)->getMock(); $organizationFactory ->expects(self::once()) ->method('makePersonContactPoint') ->with($organizationMemberCreationRequest) ->willReturn($contactPoint); $functionType = $this->getMockBuilder(FunctionType::class)->getMock(); $this->functionTypeRepository ->expects(self::once()) ->method('findOneBy') ->with(['mission' => FunctionEnum::ACCOUNTANT]) ->willReturn($functionType); $creationDate = $this->getMockBuilder(\DateTime::class)->getMock(); $access = $organizationFactory->makeAccess( $organizationMemberCreationRequest, FunctionEnum::ACCOUNTANT, $creationDate, 1 ); $this->assertInstanceOf(Access::class, $access); $this->assertEquals( 'bob', $access->getPerson()->getUsername() ); $this->assertTrue( strlen($access->getPerson()->getPassword()) === 32 ); $this->assertEquals( 'Bob', $access->getPerson()->getName() ); $this->assertEquals( 'Bobby', $access->getPerson()->getGivenName() ); $this->assertEquals( [$personAddressPostal], $access->getPerson()->getPersonAddressPostal()->toArray() ); $this->assertEquals( [$contactPoint], $access->getPerson()->getContactPoints()->toArray() ); $this->assertEquals( $functionType, $access->getOrganizationFunction()->first()->getFunctionType() ); $this->assertEquals( $creationDate, $access->getOrganizationFunction()->first()->getStartDate() ); } public function testMakeAccessNewPersonUsernameAlreadyInUse(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeAccess'); $organizationMemberCreationRequest = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock(); $organizationMemberCreationRequest->method('getUsername')->willReturn('bob'); $organizationMemberCreationRequest->method('getName')->willReturn('Bob'); $organizationMemberCreationRequest->method('getGivenName')->willReturn('bOBBy'); $organizationMemberCreationRequest->method('getGender')->willReturn(GenderEnum::MISTER); $person = $this->getMockBuilder(Person::class)->getMock(); $this->personRepository ->method('findOneBy') ->with(['username' => 'bob'], null) ->willReturn($person); $organizationFactory ->expects(self::never()) ->method('makePersonPostalAddress'); $organizationFactory ->expects(self::never()) ->method('makePersonContactPoint'); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('Username already in use : bob'); $creationDate = $this->getMockBuilder(\DateTime::class)->getMock(); $organizationFactory->makeAccess( $organizationMemberCreationRequest, FunctionEnum::ADHERENT, $creationDate, 1 ); } public function testMakeAccessExistingPerson(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeAccess'); $person = $this->getMockBuilder(Person::class)->getMock(); $this->personRepository ->expects(self::once()) ->method('find') ->with(123) ->willReturn($person); $creationDate = $this->getMockBuilder(\DateTime::class)->getMock(); $functionType = $this->getMockBuilder(FunctionType::class)->getMock(); $this->functionTypeRepository ->expects(self::once()) ->method('findOneBy') ->with(['mission' => FunctionEnum::ACCOUNTANT]) ->willReturn($functionType); $creationDate = $this->getMockBuilder(\DateTime::class)->getMock(); $access = $organizationFactory->makeAccess( 123, FunctionEnum::ACCOUNTANT, $creationDate, 1 ); $this->assertInstanceOf(Access::class, $access); $this->assertEquals( $person, $access->getPerson() ); $this->assertEquals( $functionType, $access->getOrganizationFunction()->first()->getFunctionType() ); $this->assertEquals( $creationDate, $access->getOrganizationFunction()->first()->getStartDate() ); } public function testMakeAccessPostalAddress(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makePersonPostalAddress'); $organizationMemberCreationRequest = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock(); $organizationMemberCreationRequest->method('getStreetAddress1')->willReturn('Aaa'); $organizationMemberCreationRequest->method('getStreetAddress2')->willReturn('Bbb'); $organizationMemberCreationRequest->method('getStreetAddress3')->willReturn(null); $organizationMemberCreationRequest->method('getPostalCode')->willReturn('00000'); $organizationMemberCreationRequest->method('getCity')->willReturn('city'); $organizationMemberCreationRequest->method('getCountryId')->willReturn(123); $country = $this->getMockBuilder(Country::class)->getMock(); $this->countryRepository ->expects(self::once()) ->method('find') ->with(123) ->willReturn($country); $creationDate = $this->getMockBuilder(\DateTime::class)->getMock(); $personPostalAddress = $organizationFactory->makePersonPostalAddress( $organizationMemberCreationRequest, $creationDate, 1 ); $this->assertEquals( AddressPostalPersonTypeEnum::ADDRESS_PRINCIPAL, $personPostalAddress->getType() ); $postalAddress = $personPostalAddress->getAddressPostal(); $this->assertEquals('Aaa', $postalAddress->getStreetAddress()); $this->assertEquals('Bbb', $postalAddress->getStreetAddressSecond()); $this->assertEquals(null, $postalAddress->getStreetAddressThird()); $this->assertEquals('00000', $postalAddress->getPostalCode()); $this->assertEquals('city', $postalAddress->getAddressCity()); $this->assertEquals($country, $postalAddress->getAddressCountry()); } public function testMakeAccessContactPoint(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makePersonContactPoint'); $organizationMemberCreationRequest = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock(); $organizationMemberCreationRequest->method('getPhone')->willReturn('+33102030405'); $organizationMemberCreationRequest->method('getEmail')->willReturn('email@domain.com'); $organizationMemberCreationRequest->method('getMobile')->willReturn('+33607080910'); $this->phoneNumberUtil ->expects(self::exactly(2)) ->method('isPossibleNumber') ->willReturnMap([ ['+33102030405', null, true], ['+33607080910', null, true], ]); $phoneNumber = $this->getMockBuilder(PhoneNumber::class)->getMock(); $mobilePhoneNumber = $this->getMockBuilder(PhoneNumber::class)->getMock(); $this->phoneNumberUtil ->expects(self::exactly(2)) ->method('parse') ->willReturnMap([ ['+33102030405', null, null, false, $phoneNumber], ['+33607080910', null, null, false, $mobilePhoneNumber], ]); $creationDate = $this->getMockBuilder(\DateTime::class)->getMock(); $contactPoint = $organizationFactory->makePersonContactPoint( $organizationMemberCreationRequest, $creationDate, 1 ); $this->assertEquals( ContactPointTypeEnum::PRINCIPAL, $contactPoint->getContactType() ); $this->assertEquals( 'email@domain.com', $contactPoint->getEmail() ); $this->assertEquals( $phoneNumber, $contactPoint->getTelphone() ); $this->assertEquals( $mobilePhoneNumber, $contactPoint->getMobilPhone() ); } public function testMakeAccessContactPointInvalidPhone(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makePersonContactPoint'); $organizationMemberCreationRequest = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock(); $organizationMemberCreationRequest->method('getUsername')->willReturn('bob'); $organizationMemberCreationRequest->method('getPhone')->willReturn('invalid'); $organizationMemberCreationRequest->method('getEmail')->willReturn('email@domain.com'); $organizationMemberCreationRequest->method('getMobile')->willReturn('+33607080910'); $this->phoneNumberUtil ->expects(self::once()) ->method('isPossibleNumber') ->with('invalid') ->willReturn(false); $this->phoneNumberUtil ->expects(self::never()) ->method('parse'); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('Phone number is invalid or missing (person: bob)'); $creationDate = $this->getMockBuilder(\DateTime::class)->getMock(); $organizationFactory->makePersonContactPoint( $organizationMemberCreationRequest, $creationDate, 1 ); } public function testMakeAccessContactPointInvalidMobilePhone(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makePersonContactPoint'); $organizationMemberCreationRequest = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock(); $organizationMemberCreationRequest->method('getUsername')->willReturn('bob'); $organizationMemberCreationRequest->method('getPhone')->willReturn('+33102030405'); $organizationMemberCreationRequest->method('getEmail')->willReturn('email@domain.com'); $organizationMemberCreationRequest->method('getMobile')->willReturn('invalid'); $this->phoneNumberUtil ->expects(self::exactly(2)) ->method('isPossibleNumber') ->willReturnMap([ ['+33102030405', null, true], ['invalid', null, false], ]); $this->phoneNumberUtil ->expects(self::never()) ->method('parse'); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('Mobile phone number is invalid (person: bob)'); $creationDate = $this->getMockBuilder(\DateTime::class)->getMock(); $organizationFactory->makePersonContactPoint( $organizationMemberCreationRequest, $creationDate, 1 ); } public function testMakePersonContactPointNoMobile(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makePersonContactPoint'); $organizationMemberCreationRequest = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock(); $organizationMemberCreationRequest->method('getPhone')->willReturn('+33102030405'); $organizationMemberCreationRequest->method('getMobile')->willReturn(null); $this->phoneNumberUtil ->expects(self::once()) ->method('isPossibleNumber') ->with('+33102030405') ->willReturn(true); $creationDate = $this->getMockBuilder(\DateTime::class)->getMock(); $contactPoint = $organizationFactory->makePersonContactPoint( $organizationMemberCreationRequest, $creationDate, 1 ); $this->assertEquals( null, $contactPoint->getMobilPhone() ); } public function testMakeSubdomain(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('makeSubdomain'); $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock(); $organizationCreationRequest->method('getSubdomain')->willReturn('subdomain'); $subdomain = $organizationFactory->makeSubdomain($organizationCreationRequest); $this->assertEquals( 'subdomain', $subdomain->getSubdomain() ); $this->assertTrue( $subdomain->isActive() ); } public function testCreateTypo3Website(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('createTypo3Website'); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization->method('getId')->willReturn(123); $response = $this->getMockBuilder(ResponseInterface::class)->disableOriginalConstructor()->getMock(); $response->method('getStatusCode')->willReturn(Response::HTTP_OK); $response->method('getContent')->willReturn('{"root_uid": 456}'); $this->typo3Service->expects(self::once())->method('createSite')->with(123)->willReturn($response); $organization->expects(self::once())->method('setCmsId')->with(456); $this->entityManager->expects(self::once())->method('persist')->with($organization); $this->entityManager->expects(self::once())->method('flush'); $result = $organizationFactory->createTypo3Website($organization); $this->assertEquals( 456, $result ); } public function testCreateTypo3WebsiteWithError(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('createTypo3Website'); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization->method('getId')->willReturn(123); $response = $this->getMockBuilder(ResponseInterface::class)->disableOriginalConstructor()->getMock(); $response->method('getStatusCode')->willReturn(Response::HTTP_FORBIDDEN); $response->method('getContent')->willReturn(''); $this->typo3Service->expects(self::once())->method('createSite')->with(123)->willReturn($response); $this->logger ->expects(self::once()) ->method('critical') ->with('/!\ A critical error happened while creating the Typo3 website'); $result = $organizationFactory->createTypo3Website($organization); $this->assertNull($result); } public function testCreateTypo3WebsiteWithInvalidResponse(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('createTypo3Website'); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization->method('getId')->willReturn(123); $response = $this->getMockBuilder(ResponseInterface::class)->disableOriginalConstructor()->getMock(); $response->method('getStatusCode')->willReturn(Response::HTTP_OK); $response->method('getContent')->willReturn('Login page'); $this->typo3Service->expects(self::once())->method('createSite')->with(123)->willReturn($response); $this->logger ->expects(self::once()) ->method('critical') ->with('/!\ A critical error happened while creating the Typo3 website'); $result = $organizationFactory->createTypo3Website($organization); $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('get') ->with('/_internal/request/adminassos/create/organization/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('get') ->with('/_internal/request/adminassos/create/organization/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.") ); } public function testDelete(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('delete'); $organizationDeletionRequest = $this->getMockBuilder(OrganizationDeletionRequest::class)->getMock(); $organizationDeletionRequest->method('getOrganizationId')->willReturn(123); $parameters = $this->getMockBuilder(Parameters::class)->getMock(); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization->method('getId')->willReturn(123); $organization->method('getParameters')->willReturn($parameters); $this->organizationRepository ->expects(self::once()) ->method('find') ->with(123) ->willReturn($organization); $this->entityManager->expects(self::once())->method('beginTransaction'); $this->entityManager->expects(self::once())->method('flush'); $this->entityManager->expects(self::once())->method('commit'); $this->entityManager->expects(self::never())->method('rollback'); $person1 = $this->getMockBuilder(Person::class)->getMock(); $person1->method('getId')->willReturn(1); $person2 = $this->getMockBuilder(Person::class)->getMock(); $person2->method('getId')->willReturn(2); $person3 = $this->getMockBuilder(Person::class)->getMock(); $person3->method('getId')->willReturn(3); $organizationFactory ->method('getFutureOrphanPersons') ->with($organization) ->willReturn([$person1, $person2, $person3]); $this->entityManager->expects(self::exactly(5))->method('remove')->withConsecutive( [$parameters], [$organization], [$person1], [$person2], [$person3], ); $organizationFactory->expects(self::once())->method('deleteTypo3Website')->with(123); $organizationFactory->expects(self::once())->method('switchDolibarrSocietyToProspect')->with(123); $this->fileManager->expects(self::once())->method('deleteOrganizationFiles')->with(123); $this->fileManager ->expects(self::exactly(3)) ->method('deletePersonFiles') ->withConsecutive([1], [2], [3]); $organizationDeletionRequest ->expects(self::once()) ->method('setStatus') ->with(OrganizationDeletionRequest::STATUS_OK); $result = $organizationFactory->delete($organizationDeletionRequest); $this->assertEquals( $organizationDeletionRequest, $result ); } public function testDeleteWithRollback(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('delete'); $organizationDeletionRequest = $this->getMockBuilder(OrganizationDeletionRequest::class)->getMock(); $organizationDeletionRequest->method('getOrganizationId')->willReturn(123); $parameters = $this->getMockBuilder(Parameters::class)->getMock(); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization->method('getParameters')->willReturn($parameters); $person1 = $this->getMockBuilder(Person::class)->getMock(); $person1->method('getId')->willReturn(1); $person2 = $this->getMockBuilder(Person::class)->getMock(); $person2->method('getId')->willReturn(2); $person3 = $this->getMockBuilder(Person::class)->getMock(); $person3->method('getId')->willReturn(3); $organizationFactory ->method('getFutureOrphanPersons') ->with($organization) ->willReturn([$person1, $person2, $person3]); $this->organizationRepository ->expects(self::once()) ->method('find') ->with(123) ->willReturn($organization); $this->entityManager->expects(self::once())->method('beginTransaction'); $this->entityManager->expects(self::never())->method('flush'); $this->entityManager->expects(self::never())->method('commit'); $this->entityManager->expects(self::once())->method('rollback'); $this->entityManager->method('remove')->willThrowException(new \Exception('some error')); $organizationFactory->expects(self::never())->method('deleteTypo3Website'); $organizationFactory->expects(self::never())->method('switchDolibarrSocietyToProspect'); $organizationDeletionRequest ->expects(self::never()) ->method('setStatus'); $this->logger ->expects(self::once()) ->method('critical') ->with($this->callback(function ($arg) { return is_string($arg) && str_contains($arg, 'An error happened, operation cancelled') && str_contains($arg, 'some error'); })); $this->expectException(\Exception::class); $organizationFactory->delete($organizationDeletionRequest); } public function testDeleteWithNonBlockingErrors(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('delete'); $organizationDeletionRequest = $this->getMockBuilder(OrganizationDeletionRequest::class)->getMock(); $organizationDeletionRequest->method('getOrganizationId')->willReturn(123); $parameters = $this->getMockBuilder(Parameters::class)->getMock(); $organization = $this->getMockBuilder(Organization::class)->getMock(); $organization->method('getId')->willReturn(123); $organization->method('getParameters')->willReturn($parameters); $person1 = $this->getMockBuilder(Person::class)->getMock(); $person1->method('getId')->willReturn(1); $person2 = $this->getMockBuilder(Person::class)->getMock(); $person2->method('getId')->willReturn(2); $person3 = $this->getMockBuilder(Person::class)->getMock(); $person3->method('getId')->willReturn(3); $organizationFactory ->method('getFutureOrphanPersons') ->with($organization) ->willReturn([$person1, $person2, $person3]); $this->organizationRepository ->expects(self::once()) ->method('find') ->with(123) ->willReturn($organization); $this->entityManager->expects(self::once())->method('beginTransaction'); $this->entityManager->expects(self::once())->method('flush'); $this->entityManager->expects(self::once())->method('commit'); $this->entityManager->expects(self::never())->method('rollback'); $this->entityManager->expects(self::exactly(5))->method('remove')->withConsecutive( [$parameters], [$organization], [$person1], [$person2], [$person3], ); $organizationFactory->expects(self::once())->method('deleteTypo3Website')->willThrowException(new \Exception('some error')); $organizationFactory->expects(self::once())->method('switchDolibarrSocietyToProspect')->willThrowException(new \Exception('some error')); $organizationDeletionRequest ->expects(self::once()) ->method('setStatus') ->with(OrganizationDeletionRequest::STATUS_OK_WITH_ERRORS); $this->fileManager ->expects(self::once()) ->method('deleteOrganizationFiles') ->with(123) ->willThrowException(new \Exception('some error')); $this->fileManager ->expects(self::exactly(3)) ->method('deletePersonFiles') ->withConsecutive([1], [2], [3]) ->willThrowException(new \Exception('some error')); $this->logger ->expects(self::exactly(6)) ->method('critical') ->withConsecutive( ['An error happened while deleting the Typo3 website, please proceed manually.'], ['An error happened while updating the Dolibarr society, please proceed manually.'], ["An error happened while deleting the organization's files, please proceed manually."], ["An error happened while deleting the person's files, please proceed manually (id=1)."], ["An error happened while deleting the person's files, please proceed manually (id=2)."], ["An error happened while deleting the person's files, please proceed manually (id=3)."], ); $result = $organizationFactory->delete($organizationDeletionRequest); $this->assertEquals( $organizationDeletionRequest, $result ); } public function testGetFutureOrphanPersons(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('getFutureOrphanPersons'); $organization = $this->getMockBuilder(Organization::class)->getMock(); $access1 = $this->getMockBuilder(Access::class)->getMock(); $person1 = $this->getMockBuilder(Person::class)->getMock(); $access1->method('getPerson')->willReturn($person1); $access2 = $this->getMockBuilder(Access::class)->getMock(); $person2 = $this->getMockBuilder(Person::class)->getMock(); $access2->method('getPerson')->willReturn($person2); $access3 = $this->getMockBuilder(Access::class)->getMock(); $person3 = $this->getMockBuilder(Person::class)->getMock(); $access3->method('getPerson')->willReturn($person3); $otherAccess1 = $this->getMockBuilder(Access::class)->getMock(); $otherAccess2 = $this->getMockBuilder(Access::class)->getMock(); $person1->method('getAccesses')->willReturn(new ArrayCollection([$access1, $otherAccess1])); $person2->method('getAccesses')->willReturn(new ArrayCollection([$access2, $otherAccess2])); $person3->method('getAccesses')->willReturn(new ArrayCollection([$access3])); $organization->method('getAccesses')->willReturn(new ArrayCollection([$access1, $access2, $access3])); $this->assertEquals( [$person3], $organizationFactory->getFutureOrphanPersons($organization) ); } public function testDeleteTypo3Website(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('deleteTypo3Website'); $this->typo3Service->expects(self::once())->method('hardDeleteSite')->with(123); $organizationFactory->deleteTypo3Website(123); } public function testSwitchDolibarrSocietyToProspect(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('switchDolibarrSocietyToProspect'); $this->dolibarrApiService ->expects(self::once()) ->method('switchSocietyToProspect') ->with(123); $organizationFactory->switchDolibarrSocietyToProspect(123); } public function testSetAdminAccountPassword(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('setAdminAccountPassword'); // Create mock organization $organization = $this->getMockBuilder(Organization::class)->getMock(); // Create mock access with adminAccess=true $access = $this->getMockBuilder(Access::class)->getMock(); // Create mock person $person = $this->getMockBuilder(Person::class)->getMock(); // Set up the access to return the person $access->method('getPerson')->willReturn($person); // Set up the AccessRepository to return the access when findAdminAccess is called $this->accessRepository->method('findAdminAccess')->with($organization)->willReturn($access); // Expect the person's setPassword method to be called with the password $person->expects(self::once())->method('setPassword')->with('Password123!'); // Expect the EntityManager's persist and flush methods to be called $this->entityManager->expects(self::once())->method('persist')->with($person); $this->entityManager->expects(self::once())->method('flush'); // Call the method with a valid password $organizationFactory->setAdminAccountPassword($organization, 'Password123!'); } public function testSetAdminAccountPasswordInvalidPassword(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('setAdminAccountPassword'); // Create mock organization $organization = $this->getMockBuilder(Organization::class)->getMock(); // Expect an exception to be thrown for an invalid password $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('Password must be at least 8 characters long and include at least one uppercase letter, one lowercase letter, one digit, and one special character.'); // Call the method with an invalid password $organizationFactory->setAdminAccountPassword($organization, 'password'); } public function testSetAdminAccountPasswordNoAdminAccount(): void { $organizationFactory = $this->getOrganizationFactoryMockFor('setAdminAccountPassword'); // Create mock organization $organization = $this->getMockBuilder(Organization::class)->getMock(); // Set up the AccessRepository to return null when findAdminAccess is called $this->accessRepository->method('findAdminAccess')->with($organization)->willReturn(null); // Expect an exception to be thrown when no admin account is found $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('No admin account found for this organization.'); // Call the method with a valid password $organizationFactory->setAdminAccountPassword($organization, 'Password123!'); } }