customerRegistryMock = $this->createMock(CustomerRegistry::class); $this->storeManagerMock = $this->getMockForAbstractClass(StoreManagerInterface::class); $this->transportBuilderMock = $this->createMock(TransportBuilder::class); $this->customerViewHelperMock = $this->createMock(View::class); $this->dataProcessorMock = $this->createMock(DataObjectProcessor::class); $contextMock = $this->createPartialMock(Context::class, ['getScopeConfig']); $this->scopeConfigMock = $this->createPartialMock( ScopeConfigInterface::class, ['getValue', 'isSetFlag'] ); $contextMock->expects($this->any()) ->method('getScopeConfig') ->willReturn($this->scopeConfigMock); $this->customerSecureMock = $this->createMock(CustomerSecure::class); $this->storeMock = $this->createMock(Store::class); $this->senderResolverMock = $this->getMockBuilder(SenderResolverInterface::class) ->onlyMethods(['resolve']) ->disableOriginalConstructor() ->getMockForAbstractClass(); $this->emulation = $this->createMock(Emulation::class); $objectManager = new ObjectManagerHelper($this); $this->model = $objectManager->getObject( EmailNotification::class, [ 'customerRegistry' => $this->customerRegistryMock, 'storeManager' => $this->storeManagerMock, 'transportBuilder' => $this->transportBuilderMock, 'customerViewHelper' => $this->customerViewHelperMock, 'dataProcessor' => $this->dataProcessorMock, 'scopeConfig' => $this->scopeConfigMock, 'senderResolver' => $this->senderResolverMock, 'emulation' => $this->emulation ] ); } /** * Test email notify when credentials changed * * @param int $testNumber * @param int $customerStoreId * @param string $oldEmail * @param string $newEmail * @param bool $isPasswordChanged * @dataProvider sendNotificationEmailsDataProvider * * @return void * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testEmailNotifyWhenCredentialsChanged( $testNumber, $customerStoreId, $oldEmail, $newEmail, $isPasswordChanged ): void { $customerData = ['key' => 'value']; $senderValues = ['name' => self::STUB_SENDER, 'email' => self::STUB_SENDER]; $expects = $this->once(); $xmlPathTemplate = EmailNotification::XML_PATH_RESET_PASSWORD_TEMPLATE; switch ($testNumber) { case 1: $xmlPathTemplate = EmailNotification::XML_PATH_RESET_PASSWORD_TEMPLATE; $expects = $this->once(); break; case 2: $xmlPathTemplate = EmailNotification::XML_PATH_CHANGE_EMAIL_TEMPLATE; $expects = $this->exactly(2); break; case 3: $xmlPathTemplate = EmailNotification::XML_PATH_CHANGE_EMAIL_AND_PASSWORD_TEMPLATE; $expects = $this->exactly(2); break; } $this->senderResolverMock ->expects($expects) ->method('resolve') ->with(self::STUB_SENDER, $customerStoreId) ->willReturn($senderValues); /** * @var MockObject $origCustomerMock */ $origCustomerMock = $this->getMockForAbstractClass(CustomerInterface::class); $origCustomerMock->expects($this->any()) ->method('getStoreId') ->willReturn($customerStoreId); $origCustomerMock->expects($this->any()) ->method('getId') ->willReturn(self::STUB_CUSTOMER_ID); $origCustomerMock->expects($this->never()) ->method('getWebsiteId'); $storeMock = $this->createMock(Store::class); $storeMock->expects($this->any()) ->method('getId') ->willReturn($customerStoreId); $this->storeManagerMock->expects(clone $expects) ->method('getStore') ->willReturn($storeMock); $websiteMock = $this->createPartialMock(Website::class, ['getStoreIds']); $websiteMock->expects($this->any()) ->method('getStoreIds') ->willReturn([$customerStoreId]); $this->storeManagerMock->expects($this->never()) ->method('getWebsite'); $customerSecureMock = $this->createMock(CustomerSecure::class); $this->customerRegistryMock->expects(clone $expects) ->method('retrieveSecureData') ->with(self::STUB_CUSTOMER_ID) ->willReturn($customerSecureMock); $this->dataProcessorMock->expects(clone $expects) ->method('buildOutputDataArray') ->with($origCustomerMock, CustomerInterface::class) ->willReturn($customerData); $this->customerViewHelperMock->expects($this->any()) ->method('getCustomerName') ->with($origCustomerMock) ->willReturn(self::STUB_CUSTOMER_NAME); $customerSecureMock->expects(clone $expects) ->method('addData') ->with($customerData) ->willReturnSelf(); $customerSecureMock->expects(clone $expects) ->method('setData') ->with('name', self::STUB_CUSTOMER_NAME) ->willReturnSelf(); /** * @var CustomerInterface|MockObject $savedCustomer */ $savedCustomer = clone $origCustomerMock; $origCustomerMock->expects($this->any()) ->method('getEmail') ->willReturn($oldEmail); $savedCustomer->expects($this->any()) ->method('getEmail') ->willReturn($newEmail); $this->scopeConfigMock->expects($this->any()) ->method('getValue') ->willReturnCallback(function (...$args) use ($xmlPathTemplate, $customerStoreId) { static $index = 0; $expectedArgs = [ [$xmlPathTemplate, ScopeInterface::SCOPE_STORE, $customerStoreId], [EmailNotification::XML_PATH_FORGOT_EMAIL_IDENTITY, ScopeInterface::SCOPE_STORE, $customerStoreId], [$xmlPathTemplate, ScopeInterface::SCOPE_STORE, $customerStoreId], [EmailNotification::XML_PATH_FORGOT_EMAIL_IDENTITY, ScopeInterface::SCOPE_STORE, $customerStoreId] ]; $returnValue = [self::STUB_EMAIL_IDENTIFIER, self::STUB_SENDER, self::STUB_EMAIL_IDENTIFIER, self::STUB_SENDER]; $index++; return $args === $expectedArgs[$index - 1] ? $returnValue[$index - 1] : null; }); $this->transportBuilderMock->expects(clone $expects) ->method('setTemplateIdentifier') ->with(self::STUB_EMAIL_IDENTIFIER) ->willReturnSelf(); $this->transportBuilderMock->expects(clone $expects) ->method('setTemplateOptions') ->with(['area' => Area::AREA_FRONTEND, 'store' => $customerStoreId]) ->willReturnSelf(); $this->transportBuilderMock->expects(clone $expects) ->method('setTemplateVars') ->with(['customer' => $customerSecureMock, 'store' => $storeMock]) ->willReturnSelf(); $this->transportBuilderMock->expects(clone $expects) ->method('setFrom') ->with($senderValues) ->willReturnSelf(); $this->transportBuilderMock->expects(clone $expects) ->method('addTo') ->willReturnCallback(function ($arg1, $arg2) use ($oldEmail, $newEmail) { if (($arg1 === $oldEmail || $arg1 === $newEmail) && $arg2 === self::STUB_CUSTOMER_NAME) { return $this->transportBuilderMock; } }); $transport = $this->getMockForAbstractClass(TransportInterface::class); $this->transportBuilderMock->expects(clone $expects) ->method('getTransport') ->willReturn($transport); $transport->expects(clone $expects) ->method('sendMessage'); $this->emulation->expects(clone $expects) ->method('startEnvironmentEmulation') ->willReturnSelf(); $this->emulation->expects(clone $expects) ->method('stopEnvironmentEmulation') ->willReturnSelf(); $this->model->credentialsChanged($savedCustomer, $oldEmail, $isPasswordChanged); } /** * Provides Emails Data Provider * * @return array */ public static function sendNotificationEmailsDataProvider(): array { return [ [ 'test_number' => 1, 'customerStoreId' => 0, 'old_email' => 'test@example.com', 'new_email' => 'test@example.com', 'is_password_changed' => true ], [ 'test_number' => 1, 'customerStoreId' => 2, 'old_email' => 'test@example.com', 'new_email' => 'test@example.com', 'is_password_changed' => true ], [ 'test_number' => 2, 'customerStoreId' => 0, 'old_email' => 'test1@example.com', 'new_email' => 'test2@example.com', 'is_password_changed' => false ], [ 'test_number' => 2, 'customerStoreId' => 2, 'old_email' => 'test1@example.com', 'new_email' => 'test2@example.com', 'is_password_changed' => false ], [ 'test_number' => 3, 'customerStoreId' => 0, 'old_email' => 'test1@example.com', 'new_email' => 'test2@example.com', 'is_password_changed' => true ], [ 'test_number' => 3, 'customerStoreId' => 2, 'old_email' => 'test1@example.com', 'new_email' => 'test2@example.com', 'is_password_changed' => true ] ]; } /** * Test Password Reminder Email Notify * * @param int $customerStoreId * * @return void * @dataProvider customerStoreIdDataProvider * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testPasswordReminder(int $customerStoreId): void { $customerData = ['key' => 'value']; $senderValues = ['name' => self::STUB_SENDER, 'email' => self::STUB_SENDER]; $storeIds = [1, 2]; $this->senderResolverMock ->expects($this->once()) ->method('resolve') ->with(self::STUB_SENDER, $customerStoreId) ->willReturn($senderValues); /** * @var CustomerInterface|MockObject $customerMock */ $customerMock = $this->getMockForAbstractClass(CustomerInterface::class); $customerMock->expects($this->never()) ->method('getWebsiteId'); $customerMock->expects($this->any()) ->method('getWebsiteId') ->willReturn(self::STUB_CUSTOMER_WEBSITE_ID); $customerMock->expects($this->any()) ->method('getStoreId') ->willReturn($customerStoreId); $customerMock->expects($this->any()) ->method('getId') ->willReturn(self::STUB_CUSTOMER_ID); $customerMock->expects($this->any()) ->method('getEmail') ->willReturn(self::STUB_CUSTOMER_EMAIL); $this->storeMock->expects($this->any()) ->method('getId') ->willReturn($customerStoreId); $this->storeManagerMock ->method('getStore') ->willReturn($this->storeMock); $websiteMock = $this->createPartialMock(Website::class, ['getStoreIds']); $websiteMock->expects($this->any()) ->method('getStoreIds') ->willReturn($storeIds); $this->storeManagerMock->expects($this->any()) ->method('getWebsite') ->with(self::STUB_CUSTOMER_WEBSITE_ID) ->willReturn($websiteMock); $this->customerRegistryMock->expects($this->once()) ->method('retrieveSecureData') ->with(self::STUB_CUSTOMER_ID) ->willReturn($this->customerSecureMock); $this->dataProcessorMock->expects($this->once()) ->method('buildOutputDataArray') ->with($customerMock, CustomerInterface::class) ->willReturn($customerData); $this->customerViewHelperMock->expects($this->any()) ->method('getCustomerName') ->with($customerMock) ->willReturn(self::STUB_CUSTOMER_NAME); $this->customerSecureMock->expects($this->once()) ->method('addData') ->with($customerData) ->willReturnSelf(); $this->customerSecureMock->expects($this->once()) ->method('setData') ->with('name', self::STUB_CUSTOMER_NAME) ->willReturnSelf(); $this->scopeConfigMock ->method('getValue') ->willReturnCallback(function (...$args) use ($customerStoreId) { static $index = 0; $expectedArgs = [ [EmailNotification::XML_PATH_REMIND_EMAIL_TEMPLATE, ScopeInterface::SCOPE_STORE, $customerStoreId], [EmailNotification::XML_PATH_FORGOT_EMAIL_IDENTITY, ScopeInterface::SCOPE_STORE, $customerStoreId] ]; $returnValue = [self::STUB_EMAIL_IDENTIFIER, self::STUB_SENDER]; $index++; return $args === $expectedArgs[$index - 1] ? $returnValue[$index - 1] : null; }); $this->mockDefaultTransportBuilder( self::STUB_EMAIL_IDENTIFIER, $customerStoreId, $senderValues, self::STUB_CUSTOMER_EMAIL, self::STUB_CUSTOMER_NAME, ['customer' => $this->customerSecureMock, 'store' => $this->storeMock] ); $this->emulation->expects($this->once()) ->method('startEnvironmentEmulation') ->willReturnSelf(); $this->emulation->expects($this->once()) ->method('stopEnvironmentEmulation') ->willReturnSelf(); $this->model->passwordReminder($customerMock); } /** * Test password reminder customer withouer store id info * * @return void * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testPasswordReminderCustomerWithoutStoreId(): void { $customerStoreId = null; $customerData = ['key' => 'value']; $senderValues = ['name' => self::STUB_SENDER, 'email' => self::STUB_SENDER]; $storeIds = [1, 2]; $defaultStoreId = reset($storeIds); $this->senderResolverMock ->expects($this->once()) ->method('resolve') ->with(self::STUB_SENDER, $defaultStoreId) ->willReturn($senderValues); /** * @var CustomerInterface|MockObject $customer */ $customer = $this->getMockForAbstractClass(CustomerInterface::class); $customer->expects($this->any()) ->method('getWebsiteId') ->willReturn(self::STUB_CUSTOMER_WEBSITE_ID); $customer->expects($this->any()) ->method('getStoreId') ->willReturn($customerStoreId); $customer->expects($this->any()) ->method('getId') ->willReturn(self::STUB_CUSTOMER_ID); $customer->expects($this->any()) ->method('getEmail') ->willReturn(self::STUB_CUSTOMER_EMAIL); $this->storeMock->expects($this->any()) ->method('getId') ->willReturn($defaultStoreId); $this->storeManagerMock ->method('getStore') ->with($defaultStoreId) ->willReturnOnConsecutiveCalls($this->storeMock, $this->storeMock); $websiteMock = $this->createPartialMock(Website::class, ['getStoreIds']); $websiteMock->expects($this->any()) ->method('getStoreIds') ->willReturn($storeIds); $this->storeManagerMock->expects($this->any()) ->method('getWebsite') ->with(self::STUB_CUSTOMER_WEBSITE_ID) ->willReturn($websiteMock); $this->customerRegistryMock->expects($this->once()) ->method('retrieveSecureData') ->with(self::STUB_CUSTOMER_ID) ->willReturn($this->customerSecureMock); $this->dataProcessorMock->expects($this->once()) ->method('buildOutputDataArray') ->with($customer, CustomerInterface::class) ->willReturn($customerData); $this->customerViewHelperMock->expects($this->any()) ->method('getCustomerName') ->with($customer) ->willReturn(self::STUB_CUSTOMER_NAME); $this->customerSecureMock->expects($this->once()) ->method('addData') ->with($customerData) ->willReturnSelf(); $this->customerSecureMock->expects($this->once()) ->method('setData') ->with('name', self::STUB_CUSTOMER_NAME) ->willReturnSelf(); $this->scopeConfigMock ->method('getValue') ->willReturnCallback(function (...$args) use ($defaultStoreId) { static $index = 0; $expectedArgs = [ [EmailNotification::XML_PATH_REMIND_EMAIL_TEMPLATE, ScopeInterface::SCOPE_STORE, $defaultStoreId], [EmailNotification::XML_PATH_FORGOT_EMAIL_IDENTITY, ScopeInterface::SCOPE_STORE, $defaultStoreId] ]; $returnValue = [self::STUB_EMAIL_IDENTIFIER, self::STUB_SENDER]; $index++; return $args === $expectedArgs[$index - 1] ? $returnValue[$index - 1] : null; }); $this->mockDefaultTransportBuilder( self::STUB_EMAIL_IDENTIFIER, $defaultStoreId, $senderValues, self::STUB_CUSTOMER_EMAIL, self::STUB_CUSTOMER_NAME, ['customer' => $this->customerSecureMock, 'store' => $this->storeMock] ); $this->emulation->expects($this->once()) ->method('startEnvironmentEmulation') ->willReturnSelf(); $this->emulation->expects($this->once()) ->method('stopEnvironmentEmulation') ->willReturnSelf(); $this->model->passwordReminder($customer); } /** * Test email notify for password reset confirm * * @dataProvider customerStoreIdDataProvider * @param int $customerStoreId * * @return void * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testPasswordResetConfirmation(int $customerStoreId): void { $customerData = ['key' => 'value']; $senderValues = ['name' => self::STUB_SENDER, 'email' => self::STUB_SENDER]; $this->senderResolverMock ->expects($this->once()) ->method('resolve') ->with(self::STUB_SENDER, $customerStoreId) ->willReturn($senderValues); /** * @var CustomerInterface|MockObject $customerMock */ $customerMock = $this->getMockForAbstractClass(CustomerInterface::class); $customerMock->expects($this->never()) ->method('getWebsiteId'); $customerMock->expects($this->once()) ->method('getStoreId') ->willReturn($customerStoreId); $customerMock->expects($this->any()) ->method('getId') ->willReturn(self::STUB_CUSTOMER_ID); $customerMock->expects($this->any()) ->method('getEmail') ->willReturn(self::STUB_CUSTOMER_EMAIL); $this->storeMock->expects($this->any()) ->method('getId') ->willReturn($customerStoreId); $this->storeManagerMock ->method('getStore') ->willReturn($this->storeMock); $this->customerRegistryMock->expects($this->once()) ->method('retrieveSecureData') ->with(self::STUB_CUSTOMER_ID) ->willReturn($this->customerSecureMock); $this->dataProcessorMock->expects($this->once()) ->method('buildOutputDataArray') ->with($customerMock, CustomerInterface::class) ->willReturn($customerData); $this->customerViewHelperMock->expects($this->any()) ->method('getCustomerName') ->with($customerMock) ->willReturn(self::STUB_CUSTOMER_NAME); $this->customerSecureMock->expects($this->once()) ->method('addData') ->with($customerData) ->willReturnSelf(); $this->customerSecureMock->expects($this->once()) ->method('setData') ->with('name', self::STUB_CUSTOMER_NAME) ->willReturnSelf(); $this->scopeConfigMock ->method('getValue') ->willReturnCallback(function (...$args) use ($customerStoreId) { static $index = 0; $expectedArgs = [ [EmailNotification::XML_PATH_FORGOT_EMAIL_TEMPLATE, ScopeInterface::SCOPE_STORE, $customerStoreId], [EmailNotification::XML_PATH_FORGOT_EMAIL_IDENTITY, ScopeInterface::SCOPE_STORE, $customerStoreId] ]; $returnValue = [self::STUB_EMAIL_IDENTIFIER, self::STUB_SENDER]; $index++; return $args === $expectedArgs[$index - 1] ? $returnValue[$index - 1] : null; }); $this->mockDefaultTransportBuilder( self::STUB_EMAIL_IDENTIFIER, $customerStoreId, $senderValues, self::STUB_CUSTOMER_EMAIL, self::STUB_CUSTOMER_NAME, ['customer' => $this->customerSecureMock, 'store' => $this->storeMock] ); $this->emulation->expects($this->once()) ->method('startEnvironmentEmulation') ->willReturnSelf(); $this->emulation->expects($this->once()) ->method('stopEnvironmentEmulation') ->willReturnSelf(); $this->model->passwordResetConfirmation($customerMock); } /** * Test email notify with new account * * @dataProvider customerStoreIdDataProvider * @param int $customerStoreId * * @return void * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testNewAccount(int $customerStoreId): void { $customerData = ['key' => 'value']; $senderValues = ['name' => self::STUB_SENDER, 'email' => self::STUB_SENDER]; $this->senderResolverMock ->expects($this->once()) ->method('resolve') ->with(self::STUB_SENDER, $customerStoreId) ->willReturn($senderValues); /** * @var CustomerInterface|MockObject $customer */ $customer = $this->getMockForAbstractClass(CustomerInterface::class); $customer->expects($this->never()) ->method('getWebsiteId'); $customer->expects($this->any()) ->method('getStoreId') ->willReturn($customerStoreId); $customer->expects($this->any()) ->method('getId') ->willReturn(self::STUB_CUSTOMER_ID); $customer->expects($this->any()) ->method('getEmail') ->willReturn(self::STUB_CUSTOMER_EMAIL); $this->storeMock->expects($this->any()) ->method('getId') ->willReturn($customerStoreId); $this->storeManagerMock->expects($this->once()) ->method('getStore') ->with($customerStoreId) ->willReturn($this->storeMock); $this->customerRegistryMock->expects($this->once()) ->method('retrieveSecureData') ->with(self::STUB_CUSTOMER_ID) ->willReturn($this->customerSecureMock); $this->dataProcessorMock->expects($this->once()) ->method('buildOutputDataArray') ->with($customer, CustomerInterface::class) ->willReturn($customerData); $this->customerViewHelperMock->expects($this->any()) ->method('getCustomerName') ->with($customer) ->willReturn(self::STUB_CUSTOMER_NAME); $this->customerSecureMock->expects($this->once()) ->method('addData') ->with($customerData) ->willReturnSelf(); $this->customerSecureMock->expects($this->once()) ->method('setData') ->with('name', self::STUB_CUSTOMER_NAME) ->willReturnSelf(); $this->scopeConfigMock ->method('getValue') ->willReturnCallback(function (...$args) use ($customerStoreId) { static $index = 0; $expectedArgs = [ [EmailNotification::XML_PATH_REGISTER_EMAIL_TEMPLATE, ScopeInterface::SCOPE_STORE, $customerStoreId], [EmailNotification::XML_PATH_REGISTER_EMAIL_IDENTITY, ScopeInterface::SCOPE_STORE, $customerStoreId] ]; $returnValue = [self::STUB_EMAIL_IDENTIFIER, self::STUB_SENDER]; $index++; return $args === $expectedArgs[$index - 1] ? $returnValue[$index - 1] : null; }); $this->mockDefaultTransportBuilder( self::STUB_EMAIL_IDENTIFIER, $customerStoreId, $senderValues, self::STUB_CUSTOMER_EMAIL, self::STUB_CUSTOMER_NAME, ['customer' => $this->customerSecureMock, 'back_url' => '', 'store' => $this->storeMock] ); $this->emulation->expects($this->once()) ->method('startEnvironmentEmulation') ->willReturnSelf(); $this->emulation->expects($this->once()) ->method('stopEnvironmentEmulation') ->willReturnSelf(); $this->model->newAccount( $customer, EmailNotification::NEW_ACCOUNT_EMAIL_REGISTERED, '', $customerStoreId ); } /** * DataProvider customer store * * @return array */ public static function customerStoreIdDataProvider():array { return [ ['customerStoreId' => 0], ['customerStoreId' => 2] ]; } /** * Create default mock for $this->transportBuilderMock. * * @param string $templateIdentifier * @param int $customerStoreId * @param array $senderValues * @param string $customerEmail * @param string $customerName * @param array $templateVars * * @return void */ private function mockDefaultTransportBuilder( string $templateIdentifier, int $customerStoreId, array $senderValues, string $customerEmail, string $customerName, array $templateVars = [] ): void { $transportMock = $this->getMockForAbstractClass(TransportInterface::class); $this->transportBuilderMock->expects($this->once()) ->method('setTemplateIdentifier') ->with($templateIdentifier) ->willReturnSelf(); $this->transportBuilderMock->expects($this->once()) ->method('setTemplateOptions') ->with(['area' => Area::AREA_FRONTEND, 'store' => $customerStoreId]) ->willReturnSelf(); $this->transportBuilderMock->expects($this->once()) ->method('setTemplateVars') ->with($templateVars) ->willReturnSelf(); $this->transportBuilderMock->expects($this->once()) ->method('setFrom') ->with($senderValues) ->willReturnSelf(); $this->transportBuilderMock->expects($this->once()) ->method('addTo') ->with($customerEmail, $customerName) ->willReturnSelf(); $this->transportBuilderMock->expects($this->once()) ->method('getTransport') ->willReturn($transportMock); $transportMock->expects($this->once()) ->method('sendMessage'); } }