package ca.intelliware.ihtsdo.mlds.web.rest;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.Arrays;
import org.hamcrest.Matcher;
import org.joda.time.LocalDate;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.AdditionalAnswers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import ca.intelliware.ihtsdo.mlds.domain.Affiliate;
import ca.intelliware.ihtsdo.mlds.domain.AffiliateType;
import ca.intelliware.ihtsdo.mlds.domain.ApprovalState;
import ca.intelliware.ihtsdo.mlds.domain.CommercialUsage;
import ca.intelliware.ihtsdo.mlds.domain.CommercialUsagePeriod;
import ca.intelliware.ihtsdo.mlds.domain.UsageReportState;
import ca.intelliware.ihtsdo.mlds.repository.AffiliateRepository;
import ca.intelliware.ihtsdo.mlds.repository.CommercialUsageRepository;
import ca.intelliware.ihtsdo.mlds.service.CommercialUsageAuditEvents;
import ca.intelliware.ihtsdo.mlds.service.CommercialUsageAuthorizationChecker;
import ca.intelliware.ihtsdo.mlds.service.CommercialUsageResetter;
@RunWith(MockitoJUnitRunner.class)
public class CommercialUsageResource_CreateNewSubmission_Test {
@Mock
AffiliateRepository affiliateRepository;
@Mock
CommercialUsageAuthorizationChecker authorizationChecker;
@Mock
CommercialUsageRepository commercialUsageRepository;
@Mock
CommercialUsageAuditEvents commercialUsageAuditEvents;
@Mock
CommercialUsageResetter commercialUsageResetter;
CommercialUsageResource commercialUsageResource;
private MockMvc restCommercialUsageResource;
private Affiliate affiliate;
@Before
public void setup() {
commercialUsageResource = new CommercialUsageResource();
commercialUsageResource.affiliateRepository = affiliateRepository;
commercialUsageResource.authorizationChecker = authorizationChecker;
commercialUsageResource.commercialUsageRepository = commercialUsageRepository;
commercialUsageResource.commercialUsageAuditEvents = commercialUsageAuditEvents;
commercialUsageResource.commercialUsageResetter = commercialUsageResetter;
this.restCommercialUsageResource = MockMvcBuilders
.standaloneSetup(commercialUsageResource)
.setMessageConverters(new MockMvcJacksonTestSupport().getConfiguredMessageConverters())
.build();
Mockito.when(commercialUsageRepository.save(Mockito.any(CommercialUsage.class))).then(AdditionalAnswers.returnsFirstArg());
Mockito.when(commercialUsageRepository.saveAndFlush(Mockito.any(CommercialUsage.class))).then(AdditionalAnswers.returnsFirstArg());
withCommercialUsageResetter();
affiliate = new Affiliate(1L);
affiliate.setType(AffiliateType.COMMERCIAL);
Mockito.when(affiliateRepository.findOne(affiliate.getAffiliateId())).thenReturn(affiliate);
}
@Test
public void createNewSubmissionShouldCreateNewBlankUsageWhenNoExistingUsages() throws Exception {
CommercialUsagePeriod usagePeriod = withUsagePeriod("2014-01-01", "2014-06-30");
Mockito.when(commercialUsageRepository.findActiveBySamePeriod(Mockito.any(Affiliate.class), Mockito.any(LocalDate.class), Mockito.any(LocalDate.class))).thenReturn(Arrays.<CommercialUsage>asList());
Mockito.when(commercialUsageRepository.findActiveByMostRecentPeriod(Mockito.any(Affiliate.class))).thenReturn(Arrays.<CommercialUsage>asList());
final long newCommercialUsageId = 123L;
saveCommercialUsageAndAssignIdForNewEntities(newCommercialUsageId);
postCreateNewSubmission(affiliate.getAffiliateId(), usagePeriod)
.andExpect(status().isOk())
.andExpect(jsonPath("$.commercialUsageId").value(123))
.andExpect(jsonPath("$.startDate").value(jsonDateMatcher("2014-01-01")))
.andExpect(jsonPath("$.endDate").value(jsonDateMatcher("2014-06-30")))
.andExpect(jsonPath("$.type").value("COMMERCIAL"));
}
private void saveCommercialUsageAndAssignIdForNewEntities(final long newCommercialUsageId) {
Mockito.when(commercialUsageRepository.save(Mockito.any(CommercialUsage.class))).then(new Answer<CommercialUsage>() {
@Override
public CommercialUsage answer(InvocationOnMock invocation) throws Throwable {
CommercialUsage commercialUsage = (CommercialUsage) invocation.getArguments()[0];
if (commercialUsage.getCommercialUsageId() == null) {
commercialUsage.setCommercialUsageId(newCommercialUsageId);
}
return commercialUsage;
}
});
}
@Test
public void createNewSubmissionShouldReturnExistingUsageWithMatchingPeriod() throws Exception {
CommercialUsagePeriod usagePeriod = withUsagePeriod("2014-01-01", "2014-06-30");
CommercialUsage commercialUsage = new CommercialUsage(2L, affiliate);
commercialUsage.setState(UsageReportState.SUBMITTED);
Mockito.when(commercialUsageRepository.findActiveBySamePeriod(Mockito.any(Affiliate.class), Mockito.any(LocalDate.class), Mockito.any(LocalDate.class))).thenReturn(Arrays.<CommercialUsage>asList(commercialUsage));
postCreateNewSubmission(affiliate.getAffiliateId(), usagePeriod)
.andExpect(status().isOk())
.andExpect(jsonPath("$.commercialUsageId").value(2));
}
@Test
public void createNewSubmissionShouldCreateDuplicateUsageWhenNoMatchingPeriodButMostRecentPeriodPresent() throws Exception {
CommercialUsagePeriod usagePeriod = withUsagePeriod("2014-01-01", "2014-06-30");
CommercialUsage otherCommercialUsage = new CommercialUsage(2L, affiliate);
otherCommercialUsage.setStartDate(LocalDate.parse("2014-07-01"));
otherCommercialUsage.setEndDate(LocalDate.parse("2014-12-31"));
otherCommercialUsage.setType(AffiliateType.COMMERCIAL);
otherCommercialUsage.setState(UsageReportState.SUBMITTED);
Mockito.when(commercialUsageRepository.findActiveBySamePeriod(Mockito.any(Affiliate.class), Mockito.any(LocalDate.class), Mockito.any(LocalDate.class))).thenReturn(Arrays.<CommercialUsage>asList());
Mockito.when(commercialUsageRepository.findActiveByMostRecentPeriod(Mockito.any(Affiliate.class))).thenReturn(Arrays.<CommercialUsage>asList(otherCommercialUsage));
final long newCommercialUsageId = 123L;
saveCommercialUsageAndAssignIdForNewEntities(newCommercialUsageId);
postCreateNewSubmission(affiliate.getAffiliateId(), usagePeriod)
.andExpect(status().isOk())
.andExpect(jsonPath("$.commercialUsageId").value(123))
.andExpect(jsonPath("$.startDate").value(jsonDateMatcher("2014-01-01")))
.andExpect(jsonPath("$.endDate").value(jsonDateMatcher("2014-06-30")))
.andExpect(jsonPath("$.type").value("COMMERCIAL"));
}
@Test
public void createNewSubmissionShouldLogWhenNewUsageIsCreated() throws Exception {
CommercialUsagePeriod usagePeriod = withUsagePeriod("2014-01-01", "2014-06-30");
Mockito.when(commercialUsageRepository.findActiveBySamePeriod(Mockito.any(Affiliate.class), Mockito.any(LocalDate.class), Mockito.any(LocalDate.class))).thenReturn(Arrays.<CommercialUsage>asList());
Mockito.when(commercialUsageRepository.findActiveByMostRecentPeriod(Mockito.any(Affiliate.class))).thenReturn(Arrays.<CommercialUsage>asList());
final long newCommercialUsageId = 123L;
saveCommercialUsageAndAssignIdForNewEntities(newCommercialUsageId);
postCreateNewSubmission(affiliate.getAffiliateId(), usagePeriod)
.andExpect(status().isOk())
.andExpect(jsonPath("$.commercialUsageId").value(123));
Mockito.verify(commercialUsageAuditEvents).logCreationOf(Mockito.any(CommercialUsage.class));
}
private Matcher<Iterable<? extends Integer>> jsonDateMatcher(String date) {
//TODO JodaTime serializer are not setup properly for mock tests so map to basic output
LocalDate localDate = LocalDate.parse(date);
return org.hamcrest.Matchers.contains(localDate.getYear(),localDate.getMonthOfYear(),localDate.getDayOfMonth());
}
private CommercialUsagePeriod withUsagePeriod(String startDate, String endDate) {
CommercialUsagePeriod usagePeriod = new CommercialUsagePeriod();
usagePeriod.setStartDate(LocalDate.parse(startDate));
usagePeriod.setEndDate(LocalDate.parse(endDate));
return usagePeriod;
}
private void withCommercialUsageResetter() {
Mockito.doAnswer(new Answer<CommercialUsage>() {
@Override
public CommercialUsage answer(InvocationOnMock invocation) throws Throwable {
//Act as reset and save...
CommercialUsage usage = (CommercialUsage) invocation.getArguments()[0];
usage.setCommercialUsageId(null);
usage.setStartDate((LocalDate) invocation.getArguments()[1]);
usage.setEndDate((LocalDate) invocation.getArguments()[2]);
usage.setState(UsageReportState.NOT_SUBMITTED);
usage.setEffectiveTo(null);
return null;
}
}).when(commercialUsageResetter).detachAndReset(Mockito.any(CommercialUsage.class), Mockito.any(LocalDate.class), Mockito.any(LocalDate.class));
}
private ResultActions postCreateNewSubmission(long affiliateId, CommercialUsagePeriod period) throws Exception {
return restCommercialUsageResource.perform(
MockMvcRequestBuilders
.post(Routes.USAGE_REPORTS, affiliateId)
.contentType(MediaType.APPLICATION_JSON)
.content("{\"startDate\":\""+period.getStartDate()+"\",\"endDate\":\""+period.getEndDate()+"\"}")
.accept(MediaType.APPLICATION_JSON));
}
}