/** * 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.transactional; import org.jtalks.common.model.entity.Property; import org.jtalks.common.model.entity.User; import org.jtalks.common.model.permissions.GeneralPermission; import org.jtalks.jcommune.model.dao.PrivateMessageDao; import org.jtalks.jcommune.model.dao.PropertyDao; import org.jtalks.jcommune.model.dto.PageRequest; import org.jtalks.jcommune.model.entity.JCUser; import org.jtalks.jcommune.model.entity.JCommuneProperty; import org.jtalks.jcommune.model.entity.PrivateMessage; import org.jtalks.jcommune.model.entity.PrivateMessageStatus; import org.jtalks.jcommune.service.UserService; import org.jtalks.jcommune.plugin.api.exceptions.NotFoundException; import org.jtalks.jcommune.service.nontransactional.MailService; import org.jtalks.jcommune.service.nontransactional.UserDataCacheService; import org.jtalks.jcommune.service.security.SecurityService; import org.jtalks.jcommune.service.security.acl.builders.CompoundAclBuilder; import org.mockito.Matchers; import org.mockito.Mock; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.Arrays; import java.util.List; import static org.jtalks.jcommune.service.TestUtils.mockAclBuilder; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; import static org.testng.Assert.*; /** * @author Pavel Vervenko * @author Kirill Afonin * @author Max Malakhov */ public class TransactionalPrivateMessageServiceTest { private static final String PROPERTY_NAME = "property"; private static final boolean SENDING_NOTIFICATIONS_ENABLED = true; private static final boolean SENDING_NOTIFICATIONS_DISABLED = false; @Mock private PrivateMessageDao pmDao; @Mock private SecurityService securityService; @Mock private UserService userService; @Mock private UserDataCacheService userDataCache; @Mock private MailService mailService; @Mock private PropertyDao propertyDao; private JCommuneProperty sendingNotificationsEnabledProperty = JCommuneProperty.SENDING_NOTIFICATIONS_ENABLED; private TransactionalPrivateMessageService pmService; private static final long PM_ID = 1L; private static final String USERNAME = "username"; private static final JCUser JC_USER = new JCUser(USERNAME, "123@123.ru", "123"); private CompoundAclBuilder<User> aclBuilder; private static final String DRAFTS = "drafts"; private static final String OUTBOX = "outbox"; private static final String INBOX = "inbox"; private JCUser user = new JCUser(USERNAME, "email", "password"); @BeforeMethod public void setUp() throws Exception { initMocks(this); sendingNotificationsEnabledProperty.setName(PROPERTY_NAME); sendingNotificationsEnabledProperty.setPropertyDao(propertyDao); aclBuilder = mockAclBuilder(); pmService = new TransactionalPrivateMessageService(pmDao, securityService, userService, userDataCache, mailService, sendingNotificationsEnabledProperty); when(userService.getCurrentUser()).thenReturn(user); } @Test public void testGetInboxForCurrentUser() { String pageNumber = "1"; List<PrivateMessage> messages = Arrays.asList(new PrivateMessage(user, user, "Message title", "Private message body")); Page<PrivateMessage> expectedPage = new PageImpl<>(messages); when(pmDao.getAllForUser(eq(user), Matchers.<PageRequest>any())).thenReturn(expectedPage); Page<PrivateMessage> actual = pmService.getInboxForCurrentUser(pageNumber); verify(pmDao).getAllForUser(eq(user), Matchers.<PageRequest>any()); assertEquals(expectedPage, actual); } @Test public void testGetOutboxForCurrentUser() { String pageNumber = "1"; List<PrivateMessage> messages = Arrays.asList(new PrivateMessage(user, user, "Message title", "Private message body")); Page<PrivateMessage> expectedPage = new PageImpl<>(messages); when(pmDao.getAllFromUser(eq(user), Matchers.<PageRequest>any())).thenReturn(expectedPage); Page<PrivateMessage> actual = pmService.getOutboxForCurrentUser(pageNumber); verify(pmDao).getAllFromUser(eq(user), Matchers.<PageRequest>any()); assertEquals(expectedPage, actual); } @Test public void testSendMessageNotificationEnabled() throws NotFoundException { when(securityService.<User>createAclBuilder()).thenReturn(aclBuilder); when(propertyDao.getByName(PROPERTY_NAME)). thenReturn(new Property(PROPERTY_NAME, String.valueOf(SENDING_NOTIFICATIONS_ENABLED))); JC_USER.setSendPmNotification(SENDING_NOTIFICATIONS_ENABLED); PrivateMessage pm = pmService.sendMessage("body", "title", JC_USER, user); assertFalse(pm.isRead()); assertEquals(pm.getStatus(), PrivateMessageStatus.SENT); verify(userDataCache).incrementNewMessageCountFor(USERNAME); verify(pmDao).saveOrUpdate(pm); verify(aclBuilder, times(2)).grant(GeneralPermission.READ); verify(propertyDao).getByName(PROPERTY_NAME); verify(mailService, times(1)).sendReceivedPrivateMessageNotification(JC_USER, pm); } @Test public void testSendMessageNotificationDisabled() throws NotFoundException { when(securityService.<User>createAclBuilder()).thenReturn(aclBuilder); when(propertyDao.getByName(PROPERTY_NAME)). thenReturn(new Property(PROPERTY_NAME, String.valueOf(SENDING_NOTIFICATIONS_DISABLED))); JC_USER.setSendPmNotification(SENDING_NOTIFICATIONS_DISABLED); PrivateMessage pm = pmService.sendMessage("body", "title", JC_USER, user); assertFalse(pm.isRead()); assertEquals(pm.getStatus(), PrivateMessageStatus.SENT); verify(userDataCache).incrementNewMessageCountFor(USERNAME); verify(pmDao).saveOrUpdate(pm); verify(aclBuilder, times(2)).grant(GeneralPermission.READ); verify(propertyDao).getByName(PROPERTY_NAME); verify(mailService, times(0)).sendReceivedPrivateMessageNotification(JC_USER,pm); } @Test public void testGetDraftsForCurrentUser() { String pageNumber = "1"; List<PrivateMessage> messages = Arrays.asList(new PrivateMessage(user, user, "Message title", "Private message body")); Page<PrivateMessage> expectedPage = new PageImpl<>(messages); when(pmDao.getDraftsForUser(eq(user), Matchers.<PageRequest>any())).thenReturn(expectedPage); Page<PrivateMessage> actual = pmService.getDraftsForCurrentUser(pageNumber); verify(pmDao).getDraftsForUser(eq(user), Matchers.<PageRequest>any()); assertEquals(expectedPage, actual); } @Test public void testSaveDraft() throws NotFoundException { JCUser recipient = new JCUser("name", "example@example.com", "pwd"); when(securityService.<User>createAclBuilder()).thenReturn(aclBuilder); pmService.saveDraft(PM_ID, recipient, "title", "body", JC_USER); verify(pmDao).saveOrUpdate(any(PrivateMessage.class)); verify(aclBuilder).grant(GeneralPermission.WRITE); verify(aclBuilder).grant(GeneralPermission.READ); verify(aclBuilder, times(2)).on(any(PrivateMessage.class)); } @Test public void testCurrentUserNewPmCount() { int expectedPmCount = 2; when(securityService.getCurrentUserUsername()).thenReturn(USERNAME); when(pmDao.getNewMessagesCountFor(USERNAME)).thenReturn(expectedPmCount); when(userDataCache.getNewPmCountFor(USERNAME)).thenReturn(null); int newPmCount = pmService.currentUserNewPmCount(); assertEquals(newPmCount, expectedPmCount); verify(securityService).getCurrentUserUsername(); verify(pmDao).getNewMessagesCountFor(USERNAME); verify(userDataCache).putNewPmCount(USERNAME, newPmCount); } @Test public void testCurrentUserNewPmCountCached() { int expectedPmCount = 2; when(securityService.getCurrentUserUsername()).thenReturn(USERNAME); when(userDataCache.getNewPmCountFor(USERNAME)).thenReturn(expectedPmCount); int newPmCount = pmService.currentUserNewPmCount(); assertEquals(newPmCount, expectedPmCount); verify(pmDao, never()).getNewMessagesCountFor(anyString()); verify(userDataCache).getNewPmCountFor(USERNAME); } @Test public void testCurrentUserNewPmCountWithoutUser() { when(securityService.getCurrentUserUsername()).thenReturn(null); int newPmCount = pmService.currentUserNewPmCount(); assertEquals(newPmCount, 0); verify(securityService).getCurrentUserUsername(); } @Test public void testSendDraftNotificationEnabled() throws NotFoundException { when(securityService.<User>createAclBuilder()).thenReturn(aclBuilder); when(propertyDao.getByName(PROPERTY_NAME)). thenReturn(new Property(PROPERTY_NAME, String.valueOf(SENDING_NOTIFICATIONS_ENABLED))); JC_USER.setSendPmNotification(SENDING_NOTIFICATIONS_ENABLED); PrivateMessage pm = pmService.sendDraft(1L, "body", "title", JC_USER, user); assertFalse(pm.isRead()); assertEquals(pm.getStatus(), PrivateMessageStatus.SENT); verify(userDataCache).incrementNewMessageCountFor(USERNAME); verify(pmDao).saveOrUpdate(pm); verify(securityService).deleteFromAcl(pm); verify(aclBuilder, times(2)).grant(GeneralPermission.READ); verify(propertyDao).getByName(PROPERTY_NAME); verify(mailService, times(1)).sendReceivedPrivateMessageNotification(JC_USER, pm); } @Test public void testSendDraftNotificationDisabled() throws NotFoundException { when(securityService.<User>createAclBuilder()).thenReturn(aclBuilder); when(propertyDao.getByName(PROPERTY_NAME)). thenReturn(new Property(PROPERTY_NAME, String.valueOf(SENDING_NOTIFICATIONS_DISABLED))); JC_USER.setSendPmNotification(SENDING_NOTIFICATIONS_DISABLED); PrivateMessage pm = pmService.sendDraft(1L, "body", "title", JC_USER, user); assertFalse(pm.isRead()); assertEquals(pm.getStatus(), PrivateMessageStatus.SENT); verify(userDataCache).incrementNewMessageCountFor(USERNAME); verify(pmDao).saveOrUpdate(pm); verify(securityService).deleteFromAcl(pm); verify(aclBuilder, times(2)).grant(GeneralPermission.READ); verify(propertyDao).getByName(PROPERTY_NAME); verify(mailService, times(0)).sendReceivedPrivateMessageNotification(JC_USER, pm); } @Test public void testGetMessageToMe() throws NotFoundException { PrivateMessage expected = new PrivateMessage(user, user, "title", "body"); when(pmDao.get(PM_ID)).thenReturn(expected); when(pmDao.isExist(PM_ID)).thenReturn(true); PrivateMessage pm = pmService.get(PM_ID); assertEquals(pm, expected); assertTrue(pm.isRead()); verify(pmDao).saveOrUpdate(pm); verify(userDataCache).decrementNewMessageCountFor(USERNAME); } @Test(expectedExceptions = NotFoundException.class) public void testGetNotFound() throws NotFoundException { when(pmDao.isExist(PM_ID)).thenReturn(false); PrivateMessage pm = pmService.get(PM_ID); } @Test(expectedExceptions = NotFoundException.class) public void testGetNotFoundIfUserHasNoAccessToDeletedPmFromOutBox() throws NotFoundException { PrivateMessage message = new PrivateMessage(user, user, null, null); message.setStatus(PrivateMessageStatus.DELETED_FROM_OUTBOX); when(pmDao.get(PM_ID)).thenReturn(message); when(pmDao.isExist(PM_ID)).thenReturn(true); pmService.get(PM_ID); verify(pmDao).get(PM_ID); } @Test(expectedExceptions = NotFoundException.class) public void testGetNotFoundIfUserHasNoAccessToDeletePmFromInbox() throws NotFoundException { PrivateMessage message = new PrivateMessage(user, user, null, null); message.setStatus(PrivateMessageStatus.DELETED_FROM_INBOX); when(pmDao.get(PM_ID)).thenReturn(message); when(pmDao.isExist(PM_ID)).thenReturn(true); pmService.get(PM_ID); verify(pmDao).get(PM_ID); } @Test public void testGetReadAlreadyRead() throws NotFoundException { PrivateMessage expected = new PrivateMessage(user, user, "title", "body"); expected.setRead(true); when(pmDao.get(PM_ID)).thenReturn(expected); when(pmDao.isExist(PM_ID)).thenReturn(true); PrivateMessage pm = pmService.get(PM_ID); verify(pmDao, never()).saveOrUpdate(pm); verify(userDataCache, never()).decrementNewMessageCountFor(USERNAME); } @Test public void testGetPrivateMessageInDraftStatus() throws NotFoundException { PrivateMessage message = new PrivateMessage(user, user, "title", "body"); message.setStatus(PrivateMessageStatus.DRAFT); when(pmDao.get(PM_ID)).thenReturn(message); when(pmDao.isExist(PM_ID)).thenReturn(true); PrivateMessage resultMessage = pmService.get(PM_ID); assertEquals(resultMessage.isRead(), false, "Message status is draft, so message shouldn't be marked as read"); verify(pmDao, never()).saveOrUpdate(resultMessage); verify(userDataCache, never()).decrementNewMessageCountFor(USERNAME); } @Test public void testGetPrivateMessageUserToNotCurrentUser() throws NotFoundException { PrivateMessage message = new PrivateMessage(user, user, "title", "body"); JCUser currentUser = new JCUser(USERNAME, "email", "password"); when(pmDao.get(PM_ID)).thenReturn(message); when(pmDao.isExist(PM_ID)).thenReturn(true); when(userService.getCurrentUser()).thenReturn(currentUser); PrivateMessage resultMessage = pmService.get(PM_ID); assertEquals(resultMessage.isRead(), false, "The message isn't addressed to the current user, so message shouldn't be marked as read."); verify(pmDao, never()).saveOrUpdate(resultMessage); verify(userDataCache, never()).decrementNewMessageCountFor(USERNAME); } @Test public void testDeleteDrafts() throws NotFoundException { PrivateMessage message = new PrivateMessage(null, null, null, null); message.setStatus(PrivateMessageStatus.DRAFT); when(pmDao.get(1L)).thenReturn(message); when(pmDao.get(2L)).thenReturn(message); when(pmDao.isExist(1L)).thenReturn(true); when(pmDao.isExist(2L)).thenReturn(true); String resultSingle = pmService.delete(Arrays.asList(1L)); assertEquals(resultSingle, DRAFTS); verify(pmDao).delete(any(PrivateMessage.class)); String resultMultiple = pmService.delete(Arrays.asList(1L, 2L)); assertEquals(resultMultiple, DRAFTS); verify(pmDao, times(3)).delete(any(PrivateMessage.class)); } @Test public void testDeleteFromInbox() throws NotFoundException { JCUser otherUser = new JCUser(USERNAME, null, null); PrivateMessage message1 = new PrivateMessage(user, otherUser, null, null); message1.setStatus(PrivateMessageStatus.SENT); PrivateMessage message2 = new PrivateMessage(user, otherUser, null, null); message2.setStatus(PrivateMessageStatus.SENT); PrivateMessage message3 = new PrivateMessage(user, otherUser, null, null); message3.setStatus(PrivateMessageStatus.DELETED_FROM_OUTBOX); when(pmDao.get(1L)).thenReturn(message1); when(pmDao.get(2L)).thenReturn(message2); when(pmDao.get(3L)).thenReturn(message3); when(pmDao.isExist(1L)).thenReturn(true); when(pmDao.isExist(2L)).thenReturn(true); when(pmDao.isExist(3L)).thenReturn(true); String resultSingle = pmService.delete(Arrays.asList(1L)); assertEquals(resultSingle, INBOX); assertEquals(message1.getStatus(), PrivateMessageStatus.DELETED_FROM_INBOX); verify(pmDao, never()).delete(any(PrivateMessage.class)); String resultMultiple = pmService.delete(Arrays.asList(2L, 3L)); assertEquals(resultMultiple, INBOX); assertEquals(message2.getStatus(), PrivateMessageStatus.DELETED_FROM_INBOX); verify(pmDao, times(1)).delete(any(PrivateMessage.class)); } @Test public void testDeleteFromOutbox() throws NotFoundException { JCUser otherUser = new JCUser(USERNAME, null, null); PrivateMessage message1 = new PrivateMessage(otherUser, user, null, null); message1.setStatus(PrivateMessageStatus.SENT); PrivateMessage message2 = new PrivateMessage(otherUser, user, null, null); message2.setStatus(PrivateMessageStatus.SENT); PrivateMessage message3 = new PrivateMessage(otherUser, user, null, null); message3.setStatus(PrivateMessageStatus.DELETED_FROM_INBOX); when(pmDao.get(1L)).thenReturn(message1); when(pmDao.get(2L)).thenReturn(message2); when(pmDao.get(3L)).thenReturn(message3); when(pmDao.isExist(1L)).thenReturn(true); when(pmDao.isExist(2L)).thenReturn(true); when(pmDao.isExist(3L)).thenReturn(true); String resultSingle = pmService.delete(Arrays.asList(1L)); assertEquals(resultSingle, OUTBOX); assertEquals(message1.getStatus(), PrivateMessageStatus.DELETED_FROM_OUTBOX); verify(pmDao, never()).delete(any(PrivateMessage.class)); String resultMultiple = pmService.delete(Arrays.asList(2L, 3L)); assertEquals(resultMultiple, OUTBOX); assertEquals(message2.getStatus(), PrivateMessageStatus.DELETED_FROM_OUTBOX); verify(pmDao, times(1)).delete(any(PrivateMessage.class)); } @Test(expectedExceptions = NotFoundException.class) public void testDeleteNotFound() throws NotFoundException { PrivateMessage message1 = new PrivateMessage(user, user, null, null); message1.setStatus(PrivateMessageStatus.DRAFT); PrivateMessage message2 = new PrivateMessage(user, user, null, null); message2.setStatus(PrivateMessageStatus.DRAFT); when(pmDao.get(1L)).thenReturn(message1); when(pmDao.get(2L)).thenReturn(message2); when(pmDao.isExist(1L)).thenReturn(true); when(pmDao.isExist(2L)).thenReturn(true); String result = pmService.delete(Arrays.asList(1L, 1234L, 2L)); assertEquals(result, DRAFTS); verify(pmDao, times(2)).delete(any(PrivateMessage.class)); } @Test public void testHandleDraft() throws Exception{ JCUser currentUser = new JCUser(USERNAME, "email", "password"); when(userService.getCurrentUser()).thenReturn(currentUser); } /* @Test public void testIfCurrentUserHasNoAccesToDeletedOutboxPm() throws NotFoundException { PrivateMessage message1 = new PrivateMessage(user, user, null, null); message1.setStatus(PrivateMessageStatus.DELETED_FROM_OUTBOX); when(userService.getCurrentUser()).thenReturn(user); when(pmDao.get(PM_ID)).thenReturn(message1); when(pmDao.isExist(PM_ID)).thenReturn(true); boolean expectedPermision = pmService.hasCurrentUserAccessToPM(PM_ID); //todo assertFalse(expectedPermision); //todo verify(pmDao).get(PM_ID); } @Test public void testIfCurrentUserHasNoAccessToDeletedInboxPm() throws NotFoundException { PrivateMessage message1 = new PrivateMessage(user, user, null, null); message1.setStatus(PrivateMessageStatus.DELETED_FROM_INBOX); when(userService.getCurrentUser()).thenReturn(user); when(pmDao.get(PM_ID)).thenReturn(message1); when(pmDao.isExist(PM_ID)).thenReturn(true); //todo boolean expectedPermision = pmService.hasCurrentUserAccessToPM(PM_ID); //todo assertFalse(expectedPermision); //todo verify(pmDao).get(PM_ID); } @Test public void testIfCurrentUserHasAccessToAllPmExceptDeleted() throws NotFoundException { PrivateMessage message1 = new PrivateMessage(user, user, null, null); message1.setStatus(PrivateMessageStatus.DRAFT); PrivateMessage message2 = new PrivateMessage(user, user, null, null); message2.setStatus(PrivateMessageStatus.SENT); when(pmDao.get(1L)).thenReturn(message1); when(pmDao.isExist(1L)).thenReturn(true); when(pmDao.get(2L)).thenReturn(message1); when(pmDao.isExist(2L)).thenReturn(true); //todo boolean expectedPermisionForDraftPm = pmService.hasCurrentUserAccessToPM(1L); //todo boolean expectedPermisionForSentPm = pmService.hasCurrentUserAccessToPM(2L); //todo assertTrue(expectedPermisionForDraftPm); //todo assertTrue(expectedPermisionForSentPm); //todo verify(pmDao).get(1L); //todo verify(pmDao).get(2L); }*/ }