/** * Copyright (C) 2011 JTalks.org Team * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package org.jtalks.jcommune.service.nontransactional; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.tools.generic.EscapeTool; import org.jtalks.common.model.entity.Property; import org.jtalks.jcommune.model.dao.PropertyDao; import org.jtalks.jcommune.model.entity.*; import org.jtalks.jcommune.plugin.api.web.dto.TopicDto; import org.jtalks.jcommune.service.dto.EntityToDtoConverter; import org.jtalks.jcommune.service.exceptions.MailingFailedException; import org.jtalks.jcommune.plugin.api.exceptions.NotFoundException; import org.mockito.ArgumentCaptor; import org.mockito.Matchers; import org.mockito.Mock; import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.mail.MailSendException; import org.springframework.mail.SimpleMailMessage; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletWebRequest; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import java.io.IOException; import static org.jtalks.jcommune.model.entity.JCommuneProperty.SENDING_NOTIFICATIONS_ENABLED; import static org.mockito.Mockito.*; import static org.mockito.MockitoAnnotations.initMocks; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; /** * Test for {@link MailService}. * * @author Evgeniy Naumenko */ public class MailServiceTest { private static final String PROPERTY_NAME = "property"; private static final String TRUE_STRING = Boolean.TRUE.toString(); private static final String FALSE_STRING = Boolean.FALSE.toString(); private static final String FROM = "lol@wut.zz"; private static final String TO = "foo@bar.zz"; private static final String USERNAME = "user"; private static final String PASSWORD = "new_password"; @Mock private PropertyDao propertyDao; @Mock private MailSender sender; @Mock private EntityToDtoConverter converter; private JCommuneProperty notificationsEnabledProperty = SENDING_NOTIFICATIONS_ENABLED; // private MailService service; private JCUser user = new JCUser(USERNAME, TO, PASSWORD); private Topic topic = new Topic(user, "title Topic"); private Branch branch = new Branch("title Branch", "description"); private ArgumentCaptor<MimeMessage> captor; private ReloadableResourceBundleMessageSource messageSource; private TopicDto topicDto = new TopicDto(topic); private long topicId = 777; private long branchId = 7; @BeforeMethod public void setUp() { initMocks(this); // notificationsEnabledProperty.setPropertyDao(propertyDao); notificationsEnabledProperty.setName(PROPERTY_NAME); // VelocityEngine velocityEngine = new VelocityEngine(); velocityEngine.setProperty("resource.loader", "class"); velocityEngine.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); velocityEngine.setProperty("runtime.log.logsystem.class", "org.apache.velocity.runtime.log.NullLogSystem"); messageSource = new ReloadableResourceBundleMessageSource(); messageSource.setBasename("classpath:/org/jtalks/jcommune/service/bundle/TemplatesMessages"); service = new MailService(sender, FROM, velocityEngine, messageSource, notificationsEnabledProperty, new EscapeTool(), converter); MimeMessage message = new MimeMessage((Session) null); when(sender.createMimeMessage()).thenReturn(message); topicDto.setTopicUrl("/topics/" + topicId); when(converter.convertTopicToDto(any(Topic.class))).thenReturn(topicDto); captor = ArgumentCaptor.forClass(MimeMessage.class); topic.setId(topicId); branch.setId(branchId); topic.setBranch(branch); topic.setType(TopicTypeName.DISCUSSION.getName()); } @BeforeMethod public void setUpRequestContext() { MockHttpServletRequest request = new MockHttpServletRequest(); request.setScheme("http"); request.setServerName("coolsite.com"); request.setServerPort(1234); request.setContextPath("/forum"); RequestContextHolder.setRequestAttributes(new ServletWebRequest(request)); } @Test public void testSendPasswordRecoveryMail() throws Exception { enableEmailNotifications(); service.sendPasswordRecoveryMail(user, PASSWORD); this.checkMailCredentials(); assertTrue(this.getMimeMailBody().contains(USERNAME)); assertTrue(this.getMimeMailBody().contains(PASSWORD)); assertTrue(this.getMimeMailBody().contains("http://coolsite.com:1234/forum/login")); } @Test public void passwordRecoveryMailShouldNotBeSentIfNotificationsAreDisabled() throws Exception { disableEmailNotifications(); service.sendPasswordRecoveryMail(user, PASSWORD); verify(sender, never()).send(any(MimeMessage.class)); } @Test public void testSendTopicUpdatesEmail() throws Exception { enableEmailNotifications(); Post post = new Post(user, "content"); post.setId(1); topic.addPost(post); service.sendUpdatesOnSubscription(user, topic); this.checkMailCredentials(); assertTrue(this.getMimeMailBody().contains("http://coolsite.com:1234/forum/posts/1")); } @Test public void topicUpdatesEmailShouldNotBeSentIfNotificationsAreDisabled() throws Exception { disableEmailNotifications(); Post post = new Post(user, "content"); post.setId(1); topic.addPost(post); service.sendUpdatesOnSubscription(user, topic); verify(sender, never()).send(any(MimeMessage.class)); } @Test public void testSendTopicUpdateEmailCheckTitleInSubject() throws Exception { enableEmailNotifications(); Post post = new Post(user, "content"); post.setId(1); topic.addPost(post); service.sendUpdatesOnSubscription(user, topic); this.checkMailCredentials(); assertTrue(this.getMimeMailSubject().contains("title Topic")); } @Test public void testSendBranchUpdateEmail() throws Exception { enableEmailNotifications(); service.sendUpdatesOnSubscription(user, branch); this.checkMailCredentials(); assertTrue(this.getMimeMailBody().contains("http://coolsite.com:1234/forum/branches/" + branchId)); } @Test public void branchUpdateEmailShouldNotBeSentIfNotificationsAreDisabled() throws Exception { disableEmailNotifications(); service.sendUpdatesOnSubscription(user, branch); verify(sender, never()).send(any(MimeMessage.class)); } @Test public void testSendBranchUpdateEmailCheckTitleInSubject() throws Exception { enableEmailNotifications(); service.sendUpdatesOnSubscription(user, branch); this.checkMailCredentials(); assertTrue(this.getMimeMailSubject().contains("title Branch")); } @Test public void testSendReceivedPrivateMessageNotification() throws Exception { enableEmailNotifications(); PrivateMessage message = new PrivateMessage(null, null, "title", "body"); message.setId(1); service.sendReceivedPrivateMessageNotification(user, message); this.checkMailCredentials(); System.out.println(this.getMimeMailBody()); assertTrue(this.getMimeMailBody().contains("http://coolsite.com:1234/forum/pm/inbox/1")); } @Test public void receivedPrivateMessageNotificationShouldNotBeSentIfNotificationsAreDisabled() throws Exception { disableEmailNotifications(); PrivateMessage message = new PrivateMessage(null, null, "title", "body"); message.setId(1); service.sendReceivedPrivateMessageNotification(user, message); verify(sender, never()).send(any(MimeMessage.class)); } @Test public void testSendActivationMail() throws Exception { enableEmailNotifications(); JCUser user = new JCUser(USERNAME, TO, PASSWORD); service.sendAccountActivationMail(user); this.checkMailCredentials(); assertTrue(this.getMimeMailBody().contains("http://coolsite.com:1234/forum/user/activate/" + user.getUuid())); } @Test public void activationMailShouldNotBeSentIfNotificationsAreDisabled() throws Exception { disableEmailNotifications(); JCUser user = new JCUser(USERNAME, TO, PASSWORD); service.sendAccountActivationMail(user); verify(sender, never()).send(any(MimeMessage.class)); } @Test public void testSendActivationMailFail() { enableEmailNotifications(); Exception fail = new MailSendException(""); doThrow(fail).when(sender).send(Matchers.<SimpleMailMessage>any()); service.sendAccountActivationMail(new JCUser(USERNAME, TO, PASSWORD)); } @Test(expectedExceptions = MailingFailedException.class) public void testRestorePasswordFail() throws NotFoundException, MailingFailedException { enableEmailNotifications(); Exception fail = new MailSendException(""); doThrow(fail).when(sender).send(Matchers.<MimeMessage>any()); service.sendPasswordRecoveryMail(user, PASSWORD); } @Test public void testTopicUpdateNotificationFail() throws NotFoundException { enableEmailNotifications(); Exception fail = new MailSendException(""); doThrow(fail).when(sender).send(Matchers.<SimpleMailMessage>any()); service.sendUpdatesOnSubscription(user, topic); } @Test public void testBranchUpdateNotificationFail() throws NotFoundException { enableEmailNotifications(); Exception fail = new MailSendException(""); doThrow(fail).when(sender).send(Matchers.<SimpleMailMessage>any()); service.sendUpdatesOnSubscription(user, branch); } @Test public void testSendReceivedPrivateMessageNotificationFail() { enableEmailNotifications(); Exception fail = new MailSendException(""); doThrow(fail).when(sender).send(Matchers.<SimpleMailMessage>any()); service.sendReceivedPrivateMessageNotification(user, new PrivateMessage(null, null, null, null)); } @Test public void sendUserMentionedNotificationShouldSentIt() throws Exception { enableEmailNotifications(); long postId = 25l; service.sendUserMentionedNotification(user, postId); this.checkMailCredentials(); assertTrue(this.getMimeMailBody().contains(USERNAME)); assertTrue(this.getMimeMailBody().contains("http://coolsite.com:1234/forum/posts/" + postId)); } @Test public void sendUserMentionedNotificationShouldNotSentWhenForumNotificationsAreDisabled() throws Exception { disableEmailNotifications(); long postId = 25l; service.sendUserMentionedNotification(user, postId); verify(sender, never()).send(any(MimeMessage.class)); } private String getMimeMailBody() throws IOException, MessagingException { return ((MimeMultipart) ((MimeMultipart) ((MimeMultipart) captor.getValue().getContent()).getBodyPart(0). getDataHandler().getContent()).getBodyPart(0).getDataHandler().getContent()).getBodyPart(0). getDataHandler().getContent().toString();//sorry } private String getMimeMailSubject() throws IOException, MessagingException { return captor.getValue().getSubject(); } private void checkMailCredentials() throws MessagingException { verify(sender).send(captor.capture()); assertEquals(captor.getValue().getRecipients(Message.RecipientType.TO).length, 1); InternetAddress actualTo = (InternetAddress) captor.getValue().getRecipients(Message.RecipientType.TO)[0]; assertEquals(actualTo.getAddress(), TO); InternetAddress actualFrom = (InternetAddress) captor.getValue().getFrom()[0]; assertEquals(actualFrom.getAddress(), FROM); } private void disableEmailNotifications() { Property disabledProperty = new Property(PROPERTY_NAME, FALSE_STRING); when(propertyDao.getByName(PROPERTY_NAME)).thenReturn(disabledProperty); } private void enableEmailNotifications() { Property enabledProperty = new Property(PROPERTY_NAME, TRUE_STRING); when(propertyDao.getByName(PROPERTY_NAME)).thenReturn(enabledProperty); } @Test public void testSendRemovingTopicMailCurrentUserAware() throws Exception{ enableEmailNotifications(); service.sendRemovingTopicMail(user, topic, "admin"); this.checkMailCredentials(); String subjectTemplate = messageSource.getMessage("removeTopic.subject", new Object[]{}, user.getLanguage().getLocale()); String bodyTemplate = messageSource.getMessage("removeTopic.content", new Object[]{}, user.getLanguage().getLocale()); assertEquals(this.getMimeMailSubject(), subjectTemplate); assertTrue(this.getMimeMailBody().contains(bodyTemplate)); } @Test public void removingTopicMailCurrentUserAwareShouldNotBeSentWhenForumNotificationsAreDisabled() throws Exception { disableEmailNotifications(); service.sendRemovingTopicMail(user, topic, "admin"); verify(sender, never()).send(any(MimeMessage.class)); } @Test public void testSendRemovingTopicWithCodeReviewMailCurrentUserAware() throws Exception { enableEmailNotifications(); topic.setType(TopicTypeName.CODE_REVIEW.getName()); service.sendRemovingTopicMail(user, topic, "admin"); this.checkMailCredentials(); String subjectTemplate = messageSource.getMessage("removeCodeReview.subject", new Object[]{}, user.getLanguage().getLocale()); String bodyTemplate = messageSource.getMessage("removeCodeReview.content", new Object[]{}, user.getLanguage().getLocale()); assertEquals(this.getMimeMailSubject(), subjectTemplate); assertTrue(this.getMimeMailBody().contains(bodyTemplate)); } @Test public void testSendTopicCreationMail() throws Exception { enableEmailNotifications(); branch.addTopic(topic); service.sendTopicCreationMail(user, topic); this.checkMailCredentials(); String subjectTemplate = messageSource.getMessage("subscriptionNotification.subject", new Object[]{}, user.getLanguage().getLocale()); String bodyTemplate = messageSource.getMessage("branchSubscriptionNotification.content", new Object[]{}, user.getLanguage().getLocale()); assertEquals(this.getMimeMailSubject(), subjectTemplate + ": " + branch.getName()); assertTrue(this.getMimeMailBody().contains(bodyTemplate)); assertTrue(this.getMimeMailBody().contains("http://coolsite.com:1234/forum/topics/" + topic.getId())); assertTrue(this.getMimeMailBody().contains("http://coolsite.com:1234/forum/branches/" + branchId + "/unsubscribe")); } @Test public void topicCreationMailShouldNotSentWhenForumNotificationsAreDisabled() throws Exception { disableEmailNotifications(); branch.addTopic(topic); service.sendTopicCreationMail(user, topic); verify(sender, never()).send(any(MimeMessage.class)); } }