entityManager = $this->getMockBuilder(EntityManagerInterface::class)->disableOriginalConstructor()->getMock(); $this->mailer = $this->getMockBuilder(Mailer::class)->disableOriginalConstructor()->getMock(); $this->publicBaseUrl = 'https://example.com'; $this->adminBaseUrl = 'https://admin.example.com'; $this->organizationFactory = $this->getMockBuilder(OrganizationFactory::class)->disableOriginalConstructor()->getMock(); $this->serializer = $this->getMockBuilder(SerializerInterface::class)->disableOriginalConstructor()->getMock(); $this->logger = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock(); $this->messageBus = $this->getMockBuilder(MessageBusInterface::class)->disableOriginalConstructor()->getMock(); $this->trial = $this->getMockBuilder(Trial::class)->disableOriginalConstructor()->getMock(); $this->faqUrl = 'https://faq.example.com'; $this->softwareWebsiteUrl = 'https://software.example.com'; } private function getShopServiceMockFor(string $methodName): TestableShopService|MockObject { $shopService = $this ->getMockBuilder(TestableShopService::class) ->setConstructorArgs( [ $this->entityManager, $this->mailer, $this->publicBaseUrl, $this->adminBaseUrl, $this->organizationFactory, $this->serializer, $this->logger, $this->messageBus, $this->trial, $this->faqUrl, $this->softwareWebsiteUrl, ] ) ->setMethodsExcept([$methodName]) ->getMock(); return $shopService; } public function tearDown(): void { DatesUtils::clearFakeDatetime(); } /** * Test registerNewShopRequest method. */ public function testRegisterNewShopRequest(): void { $shopService = $this->getShopServiceMockFor('registerNewShopRequest'); $type = ShopRequestType::NEW_STRUCTURE_ARTIST_PREMIUM_TRIAL; $data = [ 'representativeEmail' => 'test@example.com', 'representativeFirstName' => 'John', 'representativeLastName' => 'Doe', 'structureName' => 'Test Structure', ]; $shopRequest = $this->getMockBuilder(ShopRequest::class)->getMock(); $shopService->expects(self::once()) ->method('controlShopRequestData') ->with($type, $data); $shopService->expects(self::once()) ->method('createRequest') ->with($type, $data) ->willReturn($shopRequest); $shopService->expects(self::once()) ->method('sendRequestValidationLink') ->with($shopRequest); $result = $shopService->registerNewShopRequest($type, $data); $this->assertSame($shopRequest, $result); } /** * Test controlShopRequestData method for NEW_STRUCTURE_ARTIST_PREMIUM_TRIAL type. */ public function testControlShopRequestDataForNewStructureArtistPremiumTrial(): void { $shopService = $this->getShopServiceMockFor('controlShopRequestData'); $type = ShopRequestType::NEW_STRUCTURE_ARTIST_PREMIUM_TRIAL; $data = [ 'representativeEmail' => 'test@example.com', 'representativeFirstName' => 'John', 'representativeLastName' => 'Doe', 'structureName' => 'Test Structure', ]; $shopService->expects(self::once()) ->method('validateNewStructureArtistPremiumTrialRequest') ->with($data); $shopService->controlShopRequestData($type, $data); } /** * Test processShopRequest method for NEW_STRUCTURE_ARTIST_PREMIUM_TRIAL type. */ public function testProcessShopRequest(): void { $shopService = $this->getShopServiceMockFor('processShopRequest'); $shopRequest = $this->getMockBuilder(ShopRequest::class)->getMock(); $shopRequest->method('getType')->willReturn(ShopRequestType::NEW_STRUCTURE_ARTIST_PREMIUM_TRIAL); $shopRequest->method('getToken')->willReturn('test-token'); $this->messageBus ->expects(self::once()) ->method('dispatch') ->with(self::callback(function ($message) { return $message instanceof NewStructureArtistPremiumTrial && $message->getToken() === 'test-token'; })) ->willReturn(new Envelope(new NewStructureArtistPremiumTrial('azerty'))); $shopRequest ->expects(self::once()) ->method('setStatus') ->with(ShopRequestStatus::VALIDATED); $this->entityManager->expects(self::once()) ->method('persist') ->with($shopRequest); $this->entityManager->expects(self::once()) ->method('flush'); $shopService->processShopRequest($shopRequest); } /** * Test createRequest method. */ public function testCreateRequest(): void { $shopService = $this->getShopServiceMockFor('createRequest'); $uuidRx = '/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i'; $type = ShopRequestType::NEW_STRUCTURE_ARTIST_PREMIUM_TRIAL; $data = [ 'representativeEmail' => 'test@example.com', 'representativeFirstName' => 'John', 'representativeLastName' => 'Doe', 'structureName' => 'Test Structure', ]; $this->entityManager->expects(self::once()) ->method('persist') ->with(self::callback(function ($shopRequest) use ($type, $data, $uuidRx) { return $shopRequest instanceof ShopRequest && $shopRequest->getType() === $type && $shopRequest->getData() === $data && preg_match($uuidRx, $shopRequest->getToken()); })); $this->entityManager->expects(self::once()) ->method('flush'); $result = $shopService->createRequest($type, $data); $this->assertInstanceOf(ShopRequest::class, $result); $this->assertSame($type, $result->getType()); $this->assertSame($data, $result->getData()); $this->assertMatchesRegularExpression($uuidRx, $result->getToken()); } /** * Test sendRequestValidationLink method. */ public function testSendRequestValidationLink(): void { $shopService = $this->getShopServiceMockFor('sendRequestValidationLink'); $token = 'test-token'; $data = [ 'representativeEmail' => 'test@example.com', 'representativeFirstName' => 'John', 'representativeLastName' => 'Doe', 'structureName' => 'Test Structure', ]; $shopRequest = $this->getMockBuilder(ShopRequest::class)->getMock(); $shopRequest->method('getToken')->willReturn($token); $shopRequest->method('getData')->willReturn($data); $this->mailer ->expects(self::once()) ->method('main') ->with(self::callback(function ($model) use ($token, $data) { return $model->getToken() === $token && $model->getRepresentativeEmail() === $data['representativeEmail'] && $model->getRepresentativeFirstName() === $data['representativeFirstName'] && $model->getRepresentativeLastName() === $data['representativeLastName'] && $model->getStructureName() === $data['structureName'] && $model->getValidationUrl() === 'https://software.example.com/shop/try/validation?token='.$token; })); $shopRequest->expects(self::once()) ->method('setStatus') ->with(ShopRequestStatus::ACTIVATION_LINK_SENT); $this->entityManager->expects(self::once()) ->method('persist') ->with($shopRequest); $this->entityManager->expects(self::once()) ->method('flush'); $shopService->sendRequestValidationLink($shopRequest); } /** * Test handleNewStructureArtistPremiumTrialRequest method. */ public function testHandleNewStructureArtistPremiumTrialRequest(): void { $shopService = $this->getShopServiceMockFor('handleNewStructureArtistPremiumTrialRequest'); $token = 'test-token'; $data = [ 'representativeEmail' => 'test@example.com', 'representativeFirstName' => 'John', 'representativeLastName' => 'Doe', 'structureName' => 'Test Structure', ]; $shopRequest = $this->getMockBuilder(ShopRequest::class)->getMock(); $shopRequest->method('getToken')->willReturn($token); $shopRequest->method('getData')->willReturn($data); $this->entityManager ->expects(self::once()) ->method('find') ->with(ShopRequest::class, $token) ->willReturn($shopRequest); $trialRequest = $this->getMockBuilder(NewStructureArtistPremiumTrialRequest::class) ->getMock(); $this->serializer ->expects(self::once()) ->method('deserialize') ->with(json_encode($data), NewStructureArtistPremiumTrialRequest::class, 'json') ->willReturn($trialRequest); $organization = $this->getMockBuilder(Organization::class)->getMock(); $shopService ->expects(self::once()) ->method('createOrganization') ->with($trialRequest) ->willReturn($organization); // Add expectation for password setting $trialRequest->method('getPassword')->willReturn('Password123!'); $this->organizationFactory ->expects(self::once()) ->method('setAdminAccountPassword') ->with($organization, 'Password123!'); $this->trial ->expects(self::once()) ->method('startArtistPremiumTrialForNewStructure') ->with($organization, $trialRequest); // Mock the sendMailToSalesAdministration and sendConfirmationMailToRepresentative methods $shopService->expects(self::once()) ->method('sendMailToSalesAdministration') ->with($trialRequest); $shopService->expects(self::once()) ->method('sendConfirmationMailToRepresentative') ->with($trialRequest); $this->logger->expects(self::once()) ->method('info') ->with('Successfully processed NewStructureArtistPremiumTrial for token: '.$token); $shopService->handleNewStructureArtistPremiumTrialRequest($token); } /** * Test handleNewStructureArtistPremiumTrialRequest method with non-existent token. */ public function testHandleNewStructureArtistPremiumTrialRequestWithNonExistentToken(): void { $shopService = $this->getShopServiceMockFor('handleNewStructureArtistPremiumTrialRequest'); $this->entityManager->expects(self::once()) ->method('find') ->with(ShopRequest::class, 'non-existent-token') ->willReturn(null); $this->logger->expects(self::once()) ->method('error') ->with('Cannot find ShopRequest with token: non-existent-token'); $shopService->handleNewStructureArtistPremiumTrialRequest('non-existent-token'); } /** * Test handleNewStructureArtistPremiumTrialRequest method when an exception occurs. */ public function testHandleNewStructureArtistPremiumTrialRequestWithException(): void { $shopService = $this->getShopServiceMockFor('handleNewStructureArtistPremiumTrialRequest'); $token = 'test-token'; $data = [ 'representativeEmail' => 'test@example.com', 'representativeFirstName' => 'John', 'representativeLastName' => 'Doe', 'structureName' => 'Test Structure', ]; $shopRequest = $this->getMockBuilder(ShopRequest::class)->getMock(); $shopRequest->method('getToken')->willReturn($token); $shopRequest->method('getData')->willReturn($data); // Expect setStatus to be called with ERROR $shopRequest->expects(self::once()) ->method('setStatus') ->with(ShopRequestStatus::ERROR); $this->entityManager ->expects(self::once()) ->method('find') ->with(ShopRequest::class, $token) ->willReturn($shopRequest); // Simulate an exception during deserialization $this->serializer ->expects(self::once()) ->method('deserialize') ->willThrowException(new \Exception('Test exception')); // Expect persist and flush to be called to save the ERROR status $this->entityManager ->expects(self::once()) ->method('persist') ->with($shopRequest); $this->entityManager ->expects(self::once()) ->method('flush'); // Expect error to be logged $this->logger->expects(self::once()) ->method('error') ->with(self::stringContains('Error processing NewStructureArtistPremiumTrial for token: '.$token)); // Expect the exception to be re-thrown $this->expectException(\Exception::class); $this->expectExceptionMessage('Test exception'); $shopService->handleNewStructureArtistPremiumTrialRequest($token); } /** * Test createOrganization method. */ public function testCreateOrganization(): void { $shopService = $this->getShopServiceMockFor('createOrganization'); $trialRequest = $this ->getMockBuilder(NewStructureArtistPremiumTrialRequest::class) ->getMock(); $organizationCreationRequest = $this ->getMockBuilder(OrganizationCreationRequest::class) ->getMock(); $organization = $this->getMockBuilder(Organization::class)->getMock(); $shopService->expects(self::once()) ->method('createOrganizationCreationRequestFromTrialRequest') ->with($trialRequest) ->willReturn($organizationCreationRequest); $this->organizationFactory ->expects(self::once()) ->method('create') ->with($organizationCreationRequest) ->willReturn($organization); $result = $shopService->createOrganization($trialRequest); $this->assertSame($organization, $result); } /** * Test validateNewStructureArtistPremiumTrialRequest method with valid data. */ public function testValidateNewStructureArtistPremiumTrialRequest(): void { $shopService = $this->getShopServiceMockFor('validateNewStructureArtistPremiumTrialRequest'); $trialRequest = $this ->getMockBuilder(NewStructureArtistPremiumTrialRequest::class) ->getMock(); $organizationCreationRequest = $this ->getMockBuilder(OrganizationCreationRequest::class) ->getMock(); $shopService->expects(self::once()) ->method('createOrganizationCreationRequestFromTrialRequest') ->with($trialRequest) ->willReturn($organizationCreationRequest); $this->organizationFactory->expects(self::once()) ->method('interruptIfOrganizationExists') ->with($organizationCreationRequest); // Convert the trial request to an array for validation $data = [ 'representativePhone' => '+33123456789', ]; $this->serializer->expects(self::once()) ->method('deserialize') ->with(json_encode($data), NewStructureArtistPremiumTrialRequest::class, 'json') ->willReturn($trialRequest); $shopService->validateNewStructureArtistPremiumTrialRequest($data); } /** * Test createOrganizationCreationRequestFromTrialRequest method with forValidationOnly=false. */ public function testCreateOrganizationCreationRequestFromTrialRequestComplete(): void { $shopService = $this->getShopServiceMockFor('createOrganizationCreationRequestFromTrialRequest'); $trialRequest = $this->getMockBuilder(NewStructureArtistPremiumTrialRequest::class) ->getMock(); $phoneNumber = $this->createMock(PhoneNumber::class); $trialRequest->method('getStructureName')->willReturn('Test Structure'); $trialRequest->method('getCity')->willReturn('Test City'); $trialRequest->method('getPostalCode')->willReturn('12345'); $trialRequest->method('getAddress')->willReturn('Test Address'); $trialRequest->method('getAddressComplement')->willReturn('Test Address Complement'); $trialRequest->method('getRepresentativePhone')->willReturn($phoneNumber); $trialRequest->method('getStructureEmail')->willReturn('structure@example.com'); $trialRequest->method('getStructureType')->willReturn(PrincipalTypeEnum::ARTISTIC_EDUCATION_ONLY); $trialRequest->method('getLegalStatus')->willReturn(LegalEnum::ASSOCIATION_LAW_1901); $trialRequest->method('getSiren')->willReturn('123456789'); $trialRequest->method('getStructureIdentifier')->willReturn('test-structure'); // Set a fake date for testing $fakeDate = '2023-05-15 10:30:00'; DatesUtils::setFakeDatetime($fakeDate); // Create the organization creation request $result = $shopService->createOrganizationCreationRequestFromTrialRequest($trialRequest); // Verify that all fields are set $this->assertEquals('Test Structure', $result->getName()); $this->assertEquals('Test City', $result->getCity()); $this->assertEquals('12345', $result->getPostalCode()); $this->assertEquals('Test Address', $result->getStreetAddress1()); $this->assertEquals('Test Address Complement', $result->getStreetAddress2()); $this->assertEquals('structure@example.com', $result->getEmail()); $this->assertEquals(PrincipalTypeEnum::ARTISTIC_EDUCATION_ONLY, $result->getPrincipalType()); $this->assertEquals(LegalEnum::ASSOCIATION_LAW_1901, $result->getLegalStatus()); $this->assertEquals('123456789', $result->getSiretNumber()); $this->assertEquals($phoneNumber, $result->getPhoneNumber()); $this->assertEquals('test-structure', $result->getSubdomain()); $this->assertEquals(SettingsProductEnum::FREEMIUM, $result->getProduct()); $this->assertFalse($result->getCreateWebsite()); $this->assertFalse($result->isClient()); $this->assertEquals(new \DateTime($fakeDate), $result->getCreationDate()); } /** * Test sendMailToSalesAdministration method. */ public function testSendMailToSalesAdministration(): void { $shopService = $this->getShopServiceMockFor('sendMailToSalesAdministration'); $trialRequest = $this->getMockBuilder(NewStructureArtistPremiumTrialRequest::class) ->getMock(); $this->mailer ->expects(self::once()) ->method('main') ->with(self::callback(function ($model) use ($trialRequest) { return $model instanceof \App\Service\Mailer\Model\Shop\NewStructureArtistPremium\NotificationToSalesAdminModel && $model->getTrialRequest() === $trialRequest && $model->getSenderId() === \App\Enum\Access\AccessIdsEnum::ADMIN_2IOPENSERVICE->value; })); $shopService->sendMailToSalesAdministration($trialRequest); } /** * Test sendConfirmationMailToRepresentative method. */ public function testSendConfirmationMailToRepresentative(): void { $shopService = $this->getShopServiceMockFor('sendConfirmationMailToRepresentative'); $trialRequest = $this->getMockBuilder(NewStructureArtistPremiumTrialRequest::class) ->getMock(); $trialRequest->method('getStructureIdentifier')->willReturn('test-structure'); $this->mailer ->expects(self::once()) ->method('main') ->with(self::callback(function ($model) use ($trialRequest) { return $model instanceof \App\Service\Mailer\Model\Shop\NewStructureArtistPremium\ConfirmationToRepresentativeModel && $model->getTrialRequest() === $trialRequest && $model->getSenderId() === \App\Enum\Access\AccessIdsEnum::ADMIN_2IOPENSERVICE->value && $model->getAccountCreationUrl() === 'https://example.com/account/create' && $model->getFaqUrl() === 'https://faq.example.com' && $model->getAdminUsername() === 'admintest-structure' && $model->getAdminLoginUrl() === 'https://admin.example.com/#/login/'; })); $shopService->sendConfirmationMailToRepresentative($trialRequest); } }