package de.asideas.crowdsource.repository;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import de.asideas.crowdsource.domain.model.ProjectEntity;
import de.asideas.crowdsource.presentation.statistics.requests.TimeRangedStatisticsRequest;
import de.asideas.crowdsource.presentation.statistics.results.BarChartStatisticsResult;
import de.asideas.crowdsource.presentation.statistics.results.LineChartStatisticsResult;
import de.asideas.crowdsource.service.statistics.StatisticsActionUtil;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapreduce.MapReduceResults;
import org.springframework.data.mongodb.core.query.Query;
import java.util.Iterator;
import java.util.List;
import static de.asideas.crowdsource.domain.model.CommentEntity.COLLECTION_NAME;
import static de.asideas.crowdsource.repository.CommentRepositoryImpl.CHART_NAME_SUM_COMMENTS;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class CommentRepositoryImplTest {
@Mock
private MongoTemplate mongoTemplate;
@Mock
private MapReduceResults<CommentRepositoryImpl.KeyValuePair> mockedMapReduceResult;
@Mock
private Iterator mockIterator;
@InjectMocks
private CommentRepositoryImpl commentRepository;
private DateTime startDate;
private DateTime endDate;
@Before
public void setUp() {
when(mongoTemplate.mapReduce(any(Query.class), eq(COLLECTION_NAME), anyString(), anyString(), eq(CommentRepositoryImpl.KeyValuePair.class)))
.thenReturn(mockedMapReduceResult);
when(mongoTemplate.mapReduce(eq(COLLECTION_NAME), anyString(), anyString(), eq(CommentRepositoryImpl.KeyValuePair.class)))
.thenReturn(mockedMapReduceResult);
when(mockedMapReduceResult.iterator()).thenReturn(mockIterator);
}
@Test
public void sumCommentsGroupByCreatedDate_no_data_from_DB_should_return_linechart_instance_with_dates_of_timespan_and_zeros() throws Exception {
DateTime startDate = DateTime.now(DateTimeZone.UTC).minusDays(1);
DateTime endDate = DateTime.now(DateTimeZone.UTC);
LineChartStatisticsResult result = commentRepository.sumCommentsGroupByCreatedDate(
new TimeRangedStatisticsRequest(startDate, endDate));
// Verify empty result generation for empty data from db.
verify(mockIterator).hasNext();
assertThat(result.getName(), is(CHART_NAME_SUM_COMMENTS));
assertThat(result.getData().size(), is(2));
assertThat(result.getData().get(0).getLabel(), is(StatisticsActionUtil.formatDate(startDate)));
assertThat(result.getData().get(0).getData(), is(0L));
assertThat(result.getData().get(1).getLabel(), is(StatisticsActionUtil.formatDate(endDate)));
assertThat(result.getData().get(1).getData(), is(0L));
}
@Test
public void sumCommentsGroupByCreatedDate_should_call_mongo_with_timerange_query() throws Exception {
DateTime startDate = DateTime.now(DateTimeZone.UTC).minusDays(1);
DateTime endDate = DateTime.now(DateTimeZone.UTC);
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
when(mongoTemplate.mapReduce(captor.capture(), eq(COLLECTION_NAME), anyString(), anyString(), eq(CommentRepositoryImpl.KeyValuePair.class)))
.thenReturn(mockedMapReduceResult);
commentRepository.sumCommentsGroupByCreatedDate(new TimeRangedStatisticsRequest(startDate, endDate));
Query capturedTimeFilterParam = captor.getValue();
DBObject capturedQuery = capturedTimeFilterParam.getQueryObject();
assertThat(capturedQuery.get("createdDate"), instanceOf(BasicDBObject.class));
BasicDBObject createdDateFromQuery = (BasicDBObject) capturedQuery.get("createdDate");
assertThat(createdDateFromQuery.get("$gte"), instanceOf(DateTime.class));
assertThat(createdDateFromQuery.get("$lte"), instanceOf(DateTime.class));
assertThat( ((DateTime) createdDateFromQuery.get("$gte")).getMillis(), is(startDate.withTimeAtStartOfDay().getMillis()));
assertThat( ((DateTime) createdDateFromQuery.get("$lte")).getMillis(), is(endDate.withTimeAtStartOfDay().plusDays(1).getMillis()));
}
@Test
public void sumCommentsGroupByCreatedDate_should_map_results_into_linechart_representation_and_fillNonDefinedDays() {
// GIVEN
DateTime startDate = DateTime.now(DateTimeZone.UTC).minusDays(5);
DateTime existingResDate_0 = startDate.plusDays(1);
DateTime existingResDate_1 = startDate.plusDays(3);
DateTime endDate = DateTime.now(DateTimeZone.UTC);
CommentRepositoryImpl.KeyValuePair mockResult1 = new CommentRepositoryImpl.KeyValuePair("" + existingResDate_0.getMillis(), 3L);
CommentRepositoryImpl.KeyValuePair mockResult2 = new CommentRepositoryImpl.KeyValuePair("" + existingResDate_1.getMillis(), 1L);
// WHEN
when(mockIterator.hasNext()).thenReturn(true, true, false);
when(mockIterator.next()).thenReturn(mockResult1, mockResult2);
LineChartStatisticsResult result = commentRepository.sumCommentsGroupByCreatedDate(new TimeRangedStatisticsRequest(startDate, endDate));
// THEN
verify(mockIterator, times(3)).hasNext();
verify(mockIterator, times(2)).next();
assertThat(result.getName(), is(CHART_NAME_SUM_COMMENTS));
assertThat(result.getData().size(), is(6));
// Verify all intermediate dates set in result
assertThat(result.getData().get(0).getLabel(), is(StatisticsActionUtil.formatDate(startDate)));
assertThat(result.getData().get(1).getLabel(), is(StatisticsActionUtil.formatDate(existingResDate_0)));
assertThat(result.getData().get(2).getLabel(), is(StatisticsActionUtil.formatDate(existingResDate_0.plusDays(1))));
assertThat(result.getData().get(3).getLabel(), is(StatisticsActionUtil.formatDate(existingResDate_1)));
assertThat(result.getData().get(4).getLabel(), is(StatisticsActionUtil.formatDate(existingResDate_1.plusDays(1))));
assertThat(result.getData().get(5).getLabel(), is(StatisticsActionUtil.formatDate(endDate)));
// Verify expected, existing results
assertThat(result.getData().get(1).getData(), is(mockResult1.getValue()));
assertThat(result.getData().get(3).getData(), is(mockResult2.getValue()));
// Verify expected, filled results
assertThat(result.getData().get(0).getData(), is(0L));
assertThat(result.getData().get(2).getData(), is(0L));
assertThat(result.getData().get(4).getData(), is(0L));
assertThat(result.getData().get(5).getData(), is(0L));
}
@Test(expected = IllegalStateException.class)
public void sumCommentsGroupByCreatedDate_should_throw_exception_on_unparseable_data_from_db() {
startDate = DateTime.now().minusDays(1);
endDate = DateTime.now();
CommentRepositoryImpl.KeyValuePair mockResult = new CommentRepositoryImpl.KeyValuePair("test_abc", 1L);
when(mockIterator.hasNext()).thenReturn(true, false);
when(mockIterator.next()).thenReturn(mockResult);
commentRepository.sumCommentsGroupByCreatedDate(new TimeRangedStatisticsRequest(startDate, endDate));
}
@Test
public void countCommentsGroupByProject_should_sort_result() {
CommentRepositoryImpl.KeyValuePair mockResult1 = new CommentRepositoryImpl.KeyValuePair("test_a", 1L);
CommentRepositoryImpl.KeyValuePair mockResult2 = new CommentRepositoryImpl.KeyValuePair("test_b", 100L);
CommentRepositoryImpl.KeyValuePair mockResult3 = new CommentRepositoryImpl.KeyValuePair("test_c", 10L);
when(mockIterator.hasNext()).thenReturn(true, true, true, false);
when(mockIterator.next()).thenReturn(mockResult1, mockResult2,mockResult3);
when(mongoTemplate.findOne(any(Query.class), eq(ProjectEntity.class))).thenReturn(new ProjectEntity());
List<BarChartStatisticsResult> result = commentRepository.countCommentsGroupByProject(5);
assertThat(result.get(0).getCount(), is(100L));
assertThat(result.get(1).getCount(), is(10L));
assertThat(result.get(2).getCount(), is(1L));
}
@Test
public void countCommentsGroupByProject_should_limit_result() {
CommentRepositoryImpl.KeyValuePair mockResult1 = new CommentRepositoryImpl.KeyValuePair("test_a", 1L);
CommentRepositoryImpl.KeyValuePair mockResult2 = new CommentRepositoryImpl.KeyValuePair("test_b", 100L);
CommentRepositoryImpl.KeyValuePair mockResult3 = new CommentRepositoryImpl.KeyValuePair("test_c", 10L);
CommentRepositoryImpl.KeyValuePair mockResult4 = new CommentRepositoryImpl.KeyValuePair("test_e", 18L);
CommentRepositoryImpl.KeyValuePair mockResult5 = new CommentRepositoryImpl.KeyValuePair("test_f", 17L);
CommentRepositoryImpl.KeyValuePair mockResult6 = new CommentRepositoryImpl.KeyValuePair("test_g", 21L);
when(mockIterator.hasNext()).thenReturn(true, true, true, true, true, true, false);
when(mockIterator.next()).thenReturn(mockResult1, mockResult2,mockResult3, mockResult4, mockResult5, mockResult6);
when(mongoTemplate.findOne(any(Query.class), eq(ProjectEntity.class))).thenReturn(new ProjectEntity());
List<BarChartStatisticsResult> result = commentRepository.countCommentsGroupByProject(5);
assertThat(result.size(), is(5));
assertThat(result.get(0).getCount(), is(100L));
assertThat(result.get(1).getCount(), is(21L));
assertThat(result.get(2).getCount(), is(18L));
assertThat(result.get(3).getCount(), is(17L));
assertThat(result.get(4).getCount(), is(10L));
}
}