package me.moodcat.backend.rooms;
import static org.hamcrest.Matchers.contains;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import me.moodcat.api.ProfanityChecker;
import me.moodcat.api.models.ChatMessageModel;
import me.moodcat.backend.BackendTest;
import me.moodcat.backend.UnitOfWorkSchedulingService;
import me.moodcat.backend.Vote;
import me.moodcat.database.controllers.RoomDAO;
import me.moodcat.database.controllers.SongDAO;
import me.moodcat.database.controllers.UserDAO;
import me.moodcat.database.embeddables.VAVector;
import me.moodcat.database.entities.ChatMessage;
import me.moodcat.database.entities.ChatMessageEmbeddable;
import me.moodcat.database.entities.Room;
import me.moodcat.database.entities.Song;
import me.moodcat.database.entities.User;
import me.moodcat.util.JukitoRunnerSupportingMockAnnotations;
import me.moodcat.util.MockedUnitOfWorkSchedulingService;
import org.jukito.UseModules;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Spy;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
@RunWith(JukitoRunnerSupportingMockAnnotations.class)
@UseModules(RoomBackendTest.RoomBackendTestModule.class)
public class RoomBackendTest extends BackendTest {
private static UserDAO userDAO = mock(UserDAO.class);
private static RoomDAO roomDAO = mock(RoomDAO.class);
private static SongDAO songDAO = mock(SongDAO.class);
public static class RoomBackendTestModule extends AbstractModule {
@Override
protected void configure() {
install(new RoomBackendModule());
bind(SongDAO.class).toInstance(songDAO);
bind(RoomDAO.class).toInstance(roomDAO);
bind(UserDAO.class).toInstance(userDAO);
bind(UnitOfWorkSchedulingService.class).to(MockedUnitOfWorkSchedulingService.class);
}
}
@Spy
private Room room;
private List<Room> rooms;
@Inject
private MockedUnitOfWorkSchedulingService unitOfWorkSchedulingService;
@Mock
private ChatMessageFactory chatMessageFactory;
@Mock
private ProfanityChecker profanityChecker;
@Inject
private RoomBackend roomBackend;
private ArrayList<ChatMessageModel> messages;
private List<Song> songHistory;
private List<Song> songFuture;
private final static User user = createUser();
private final static ChatMessageModel chatMessage = createChatMessage(user);
@Spy
private Song song1 = createSong(1);
@Spy
private Song song2 = createSong(2);
@Before
public void setUp() throws ExecutionException, InterruptedException {
rooms = Lists.newArrayList();
rooms.add(room);
messages = Lists.newArrayList();
messages.add(chatMessage);
songHistory = Lists.newArrayList();
songFuture = Lists.newArrayList();
songFuture.add(song2);
room.setCurrentSong(song1);
room.setExclusions(Lists.newArrayList());
when(room.getId()).thenReturn(1);
when(room.getChatMessages()).thenReturn(Sets.newHashSet());
when(room.getPlayHistory()).thenReturn(songHistory);
when(room.getPlayQueue()).thenReturn(songFuture);
VAVector roomVector = new VAVector(0.5, 0.5);
when(room.getVaVector()).thenReturn(roomVector);
when(userDAO.findById(user.getId())).thenReturn(user);
when(roomDAO.listRooms()).thenReturn(rooms);
when(roomDAO.findById(room.getId())).thenReturn(room);
when(songDAO.findForDistance(eq(roomVector), Matchers.anyLong())).thenReturn(songFuture);
roomBackend.initializeRooms().get();
}
@After
public void tearDown() {
unitOfWorkSchedulingService.shutdownNow();
}
@Test
public void canSuccesfullyInstantiateRoomInstances() {
assertNotNull(roomBackend);
}
@Test
public void canSendMessage() {
final RoomInstance instance = roomBackend.getRoomInstance(1);
User user = mock(User.class);
when(user.getId()).thenReturn(1);
instance.sendMessage(chatMessage, user);
assertTrue(instance.getMessages().contains(chatMessage));
}
@Test
public void canRetrieveMessages() {
final RoomInstance instance = roomBackend.getRoomInstance(1);
User user = mock(User.class);
when(user.getId()).thenReturn(1);
instance.sendMessage(chatMessage, user);
assertTrue(instance.getMessages().contains(chatMessage));
}
@Test
public void canStoreMessages() throws InterruptedException, ExecutionException {
final RoomInstance instance = roomBackend.getRoomInstance(1);
final ChatMessageModel model = new ChatMessageModel();
model.setMessage("message");
instance.sendMessage(model, user);
instance.merge().get();
ChatMessage chatMessage = new ChatMessage();
chatMessage.setRoom(room);
chatMessage.setMessage(model.getMessage());
chatMessage.setTimestamp(model.getTimestamp());
chatMessage.setCompoundId(new ChatMessageEmbeddable(room.getId(), model.getId()));
chatMessage.setUser(user);
verify(roomDAO, atLeast(1)).merge(eq(room));
assertThat(room.getChatMessages(), contains(chatMessage));
}
@Test
public void canPlayNextSong() throws InterruptedException, ExecutionException {
final RoomInstance instance = roomBackend.getRoomInstance(1);
final Song song = room.getCurrentSong();
songHistory.add(createSong());
instance.playNext().get();
instance.merge().get();
assertNotEquals(song, room.getCurrentSong());
}
@Test
public void playSongProcessVotesAndAddsRoomToExclusionWhenTooManyDislikes()
throws InterruptedException, ExecutionException {
Song mockedSong = mock(Song.class);
when(room.getCurrentSong()).thenReturn(mockedSong);
final RoomInstance instance = roomBackend.getRoomInstance(1);
instance.addVote(user, Vote.DISLIKE);
instance.playNext().get();
verify(room).addExclusion(mockedSong);
}
@Test
public void playSongProcessVotesDoesNotAddRoomToExclusionWhenNotEngouhDislikes() {
when(room.getCurrentSong()).thenReturn(song1);
final RoomInstance instance = roomBackend.getRoomInstance(1);
instance.addVote(user, Vote.LIKE);
instance.playNext();
verify(song1, never()).addExclusionRoom(room);
}
}