package de.asideas.crowdsource.repository;
import de.asideas.crowdsource.config.MongoDBConfig;
import de.asideas.crowdsource.domain.model.CommentEntity;
import de.asideas.crowdsource.domain.model.ProjectEntity;
import de.asideas.crowdsource.domain.model.UserEntity;
import de.asideas.crowdsource.presentation.statistics.requests.TimeRangedStatisticsRequest;
import de.asideas.crowdsource.presentation.statistics.results.LineChartStatisticsResult;
import de.asideas.crowdsource.service.statistics.StatisticsActionUtil;
import de.asideas.crowdsource.testsupport.CrowdSourceTestConfig;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {MongoDBConfig.class, CrowdSourceTestConfig.class})
@IntegrationTest
public class CommentRepositoryIT {
@Autowired
private ProjectRepository projectRepository;
@Autowired
private UserRepository userRepository;
@Autowired
private CommentRepository commentRepository;
@Autowired
private MongoTemplate mongoTemplate;
private UserEntity commentedBy;
private ProjectEntity commentCreatedFor;
@Before
public void init() {
// Setup test environment
if (commentedBy == null) {
List<UserEntity> allUsers = userRepository.findAll();
if (! allUsers.isEmpty()) {
commentedBy = allUsers.get(0);
} else {
commentedBy = userRepository.save(new UserEntity("test@crowdsource.de"));
}
}
if (commentCreatedFor == null) {
List<ProjectEntity> allProjects = projectRepository.findAll();
if (! allProjects.isEmpty()) {
commentCreatedFor = allProjects.get(0);
} else {
ProjectEntity projectEntity = new ProjectEntity();
projectEntity.setCreator(commentedBy);
projectEntity.setPledgeGoal(100);
projectEntity.setDescription("abc");
projectEntity.setTitle("abc");
commentCreatedFor = projectRepository.save(projectEntity);
}
}
}
@Test
public void sumCommentsGroupByCreatedDate_returns_same_as_count_per_day_sorted_by_day_ASC() {
DateTime today = DateTime.now(DateTimeZone.UTC);
DateTime dayBefore = today.minusDays(1);
DateTime twoDaysBefore = today.minusDays(2);
long commentsCreatedAtThisDay = getCountCommentsAtDayOf(today);
long commentsCreatedAtTheDayBefore = getCountCommentsAtDayOf(dayBefore);
long commentsCreatedAtTwoDaysAgo = getCountCommentsAtDayOf(twoDaysBefore);
createComments(5, today);
createComments(3, dayBefore);
createComments(1, twoDaysBefore);
LineChartStatisticsResult result = commentRepository.sumCommentsGroupByCreatedDate(
new TimeRangedStatisticsRequest(twoDaysBefore.withTimeAtStartOfDay(),
today.plusDays(1).withTimeAtStartOfDay()));
LineChartStatisticsResult.LineChartEntry resultTwoDaysAgo = result.getData().get(0);
LineChartStatisticsResult.LineChartEntry resultOneDayAgo = result.getData().get(1);
LineChartStatisticsResult.LineChartEntry resultToday = result.getData().get(2);
assertThat(resultTwoDaysAgo.getLabel(), is(StatisticsActionUtil.formatDate(twoDaysBefore)));
assertThat(resultTwoDaysAgo.getData(), is(commentsCreatedAtTwoDaysAgo + 1));
assertThat(resultOneDayAgo.getLabel(), is(StatisticsActionUtil.formatDate(dayBefore)));
assertThat(resultOneDayAgo.getData(), is(commentsCreatedAtTheDayBefore + 3));
assertThat(resultToday.getLabel(), is(StatisticsActionUtil.formatDate(today)));
assertThat(resultToday.getData(), is(commentsCreatedAtThisDay + 5));
}
@Test
public void sumCommentsGroupByCreatedDate_should_respect_timerange_bounds_inclusive () {
DateTime today = DateTime.now(DateTimeZone.UTC);
DateTime dayBefore = today.minusDays(1);
DateTime twoDaysBefore = today.minusDays(2);
DateTime threeDaysBefore = today.minusDays(3);
long commentsCreatedAt1DayAgo = getCountCommentsAtDayOf(dayBefore);
long commentsCreatedAt2DaysAgo = getCountCommentsAtDayOf(twoDaysBefore);
createComments(5, today);
createComments(3, dayBefore);
createComments(1, twoDaysBefore);
createComments(17, threeDaysBefore);
LineChartStatisticsResult result = commentRepository.sumCommentsGroupByCreatedDate(
new TimeRangedStatisticsRequest(twoDaysBefore.withTimeAtStartOfDay(),
twoDaysBefore.plusDays(2).withTimeAtStartOfDay()));
LineChartStatisticsResult.LineChartEntry resultTwoDaysAgo = result.getData().get(0);
LineChartStatisticsResult.LineChartEntry resultOneDayAgo = result.getData().get(1);
assertThat(resultTwoDaysAgo.getLabel(), is(StatisticsActionUtil.formatDate(twoDaysBefore)));
assertThat(resultTwoDaysAgo.getData(), is(commentsCreatedAt2DaysAgo + 1));
assertThat(resultOneDayAgo.getLabel(), is(StatisticsActionUtil.formatDate(dayBefore)));
assertThat(resultOneDayAgo.getData(), is(commentsCreatedAt1DayAgo + 3));
}
private void createComments(int count, DateTime dateTime) {
for (int i = 0; i < count; i++) {
CommentEntity entity = new CommentEntity();
entity.setComment("HELLO");
entity.setProject(commentCreatedFor);
entity.setUser(commentedBy);
CommentEntity saved = commentRepository.save(entity);
// Explicitly overcome auditing enabled for dates
saved.setCreatedDate(dateTime);
commentRepository.save(saved);
}
}
private long getCountCommentsAtDayOf(DateTime date) {
DateTime start = date.withTimeAtStartOfDay();
DateTime end = date.plusDays(1).withTimeAtStartOfDay();
Query dayCreatedQuery = Query.query(Criteria.where("createdDate").gte(start).lte(end));
return mongoTemplate.count(dayCreatedQuery, CommentEntity.class);
}
}