package ca.intelliware.ihtsdo.mlds.service;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.joda.time.Instant;
import org.joda.time.LocalDate;
import org.junit.Assert;
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 ca.intelliware.ihtsdo.mlds.domain.Affiliate;
import ca.intelliware.ihtsdo.mlds.domain.UsageReportState;
import ca.intelliware.ihtsdo.mlds.domain.CommercialUsage;
import ca.intelliware.ihtsdo.mlds.repository.CommercialUsageRepository;
@RunWith(MockitoJUnitRunner.class)
public class CommercialUsageServiceTest {
@Mock
CommercialUsageAuthorizationChecker authorizationChecker;
@Mock
CommercialUsageRepository commercialUsageRepository;
@Mock
CommercialUsageAuditEvents commercialUsageAuditEvents;
@Mock
CommercialUsageResetter commercialUsageResetter;
CommercialUsageService commercialUsageService;
@Before
public void setup() {
commercialUsageService = new CommercialUsageService();
commercialUsageService.authorizationChecker = authorizationChecker;
commercialUsageService.commercialUsageRepository = commercialUsageRepository;
commercialUsageService.commercialUsageAuditEvents = commercialUsageAuditEvents;
commercialUsageService.commercialUsageResetter = commercialUsageResetter;
Mockito.when(commercialUsageRepository.save(Mockito.any(CommercialUsage.class))).then(AdditionalAnswers.returnsFirstArg());
Mockito.when(commercialUsageRepository.saveAndFlush(Mockito.any(CommercialUsage.class))).then(AdditionalAnswers.returnsFirstArg());
withCommercialUsageResetter();
}
@Test
public void transitionCommercialUsageApprovalShouldFailForUnsupportedTransitions() throws Exception {
CommercialUsage commercialUsage = withCommercialUsage(2L, UsageReportState.PENDING_INVOICE);
try {
commercialUsageService.transitionCommercialUsageApproval(commercialUsage, UsageReportTransition.SUBMIT);
Assert.fail();
} catch (IllegalStateException e) {
Assert.assertThat(e.getMessage(), matchUnsupportedApprovalTransactionException());
}
Assert.assertEquals("commercial usage unchanged", UsageReportState.PENDING_INVOICE, commercialUsage.getState());
}
private Matcher<String> matchUnsupportedApprovalTransactionException() {
return Matchers.containsString("Unsupported usage report");
}
@Test
public void transitionCommercialUsageApprovalShouldTransitionNotSubmittedToSubmittedOnSubmit() throws Exception {
CommercialUsage commercialUsage = withCommercialUsage(2L, UsageReportState.NOT_SUBMITTED);
CommercialUsage result = commercialUsageService.transitionCommercialUsageApproval(commercialUsage, UsageReportTransition.SUBMIT);
Assert.assertThat(result.getState(), Matchers.equalTo(UsageReportState.SUBMITTED));
Assert.assertThat(result.getCommercialUsageId(), Matchers.equalTo(2L));
}
@Test
public void transitionCommercialUsageApprovalShouldTransitionChangeRequestedToResubmittedOnSubmit() throws Exception {
CommercialUsage commercialUsage = withCommercialUsage(2L, UsageReportState.CHANGE_REQUESTED);
CommercialUsage result = commercialUsageService.transitionCommercialUsageApproval(commercialUsage, UsageReportTransition.SUBMIT);
Assert.assertThat(result.getState(), Matchers.equalTo(UsageReportState.RESUBMITTED));
Assert.assertThat(result.getCommercialUsageId(), Matchers.equalTo(2L));
}
@Test
public void transitionCommercialUsageApprovalShouldFailWhenRetractingPreviouslyRetractedUsage() throws Exception {
CommercialUsage commercialUsage = withCommercialUsage(2L, UsageReportState.PENDING_INVOICE);
commercialUsage.setEffectiveTo(Instant.now());
try {
commercialUsageService.transitionCommercialUsageApproval(commercialUsage, UsageReportTransition.RETRACT);
Assert.fail();
} catch (IllegalStateException e) {
Assert.assertThat(e.getMessage(), matchUnsupportedApprovalTransactionException());
}
}
@Test
public void transitionCommercialUsageApprovalShouldCreateNewUsageOnRetractInChangeRequestedState() throws Exception {
final CommercialUsage originalCommercialUsage = withCommercialUsage(2L, UsageReportState.PENDING_INVOICE);
final long postResetterId = 123;
// Note that this is working with the mocked commercialUsageResetter
Mockito.when(commercialUsageRepository.save(Mockito.any(CommercialUsage.class))).thenAnswer(duplicateCommercialUsage(postResetterId));
Mockito.when(commercialUsageRepository.saveAndFlush(Mockito.any(CommercialUsage.class))).thenAnswer(duplicateCommercialUsage(postResetterId));
CommercialUsage result = commercialUsageService.transitionCommercialUsageApproval(originalCommercialUsage,
UsageReportTransition.RETRACT);
// New commercial usage
Assert.assertThat(result.getState(), Matchers.equalTo(UsageReportState.CHANGE_REQUESTED));
Assert.assertThat(result.getCommercialUsageId(), Matchers.equalTo(123L));
// Original commercial usage
Assert.assertEquals(UsageReportState.PENDING_INVOICE, originalCommercialUsage.getState());
Assert.assertThat(originalCommercialUsage.getEffectiveTo(), org.hamcrest.Matchers.notNullValue(Instant.class));
}
private Answer<CommercialUsage> duplicateCommercialUsage( final long postResetterId) {
return new Answer<CommercialUsage>() {
@Override
public CommercialUsage answer(InvocationOnMock invocation) throws Throwable {
CommercialUsage commercialUsage = (CommercialUsage) invocation.getArguments()[0];
CommercialUsage savedDuplicate = new CommercialUsage(
commercialUsage.getCommercialUsageId() != null ? commercialUsage.getCommercialUsageId() : postResetterId,
commercialUsage.getAffiliate());
savedDuplicate.setState(commercialUsage.getState());
return savedDuplicate;
}
};
}
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.setState(UsageReportState.NOT_SUBMITTED);
return null;
}
}).when(commercialUsageResetter).detachAndReset(Mockito.any(CommercialUsage.class), Mockito.any(LocalDate.class), Mockito.any(LocalDate.class));
}
@Test
public void transitionCommercialUsageApprovalShouldTransitionSubmittedToApprovedOnReviewed() throws Exception {
CommercialUsage commercialUsage = withCommercialUsage(2L, UsageReportState.SUBMITTED);
CommercialUsage result = commercialUsageService.transitionCommercialUsageApproval(commercialUsage,
UsageReportTransition.PENDING_INVOICE);
Assert.assertThat(result.getState(), Matchers.equalTo(UsageReportState.PENDING_INVOICE));
}
@Test
public void transitionCommercialUsageApprovalShouldFailWhenReviewingInactiveUsage() throws Exception {
CommercialUsage commercialUsage = withCommercialUsage(2L, UsageReportState.SUBMITTED);
commercialUsage.setEffectiveTo(Instant.now());
try {
commercialUsageService.transitionCommercialUsageApproval(commercialUsage, UsageReportTransition.PENDING_INVOICE);
Assert.fail();
} catch (IllegalStateException e) {
Assert.assertThat(e.getMessage(), matchUnsupportedApprovalTransactionException());
}
}
@Test
public void transitionCommercialUsageApprovalShouldTransitionResubmittedToApprovedOnReviewed() throws Exception {
CommercialUsage commercialUsage = withCommercialUsage(2L, UsageReportState.RESUBMITTED);
CommercialUsage result = commercialUsageService.transitionCommercialUsageApproval(commercialUsage,
UsageReportTransition.PENDING_INVOICE);
Assert.assertThat(result.getState(), Matchers.equalTo(UsageReportState.PENDING_INVOICE));
}
private CommercialUsage withCommercialUsage(long commercialUsageId, UsageReportState approvalState) {
Affiliate affiliate = new Affiliate(1L);
CommercialUsage commercialUsage = new CommercialUsage(commercialUsageId, affiliate);
commercialUsage.setState(approvalState);
Mockito.when(commercialUsageRepository.findOne(commercialUsageId)).thenReturn(commercialUsage);
return commercialUsage;
}
}