/*
* Copyright (c) 2014. The Trustees of Indiana University.
*
* This version of the code is licensed under the MPL 2.0 Open Source license with additional
* healthcare disclaimer. If the user is an entity intending to commercialize any application
* that uses this code in a for-profit venture, please contact the copyright holder.
*/
package com.muzima.controller;
import com.muzima.api.model.Cohort;
import com.muzima.api.model.CohortData;
import com.muzima.api.model.LastSyncTime;
import com.muzima.api.service.CohortService;
import com.muzima.api.service.LastSyncTimeService;
import com.muzima.service.SntpService;
import com.muzima.utils.StringUtils;
import org.apache.lucene.queryParser.ParseException;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static com.muzima.api.model.APIName.DOWNLOAD_COHORTS;
import static com.muzima.api.model.APIName.DOWNLOAD_COHORTS_DATA;
import static java.util.Arrays.asList;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.matchers.JUnitMatchers.hasItem;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
public class CohortControllerTest {
private CohortController controller;
private CohortService cohortService;
private LastSyncTimeService lastSyncTimeService;
private LastSyncTime lastSyncTime;
private Date anotherMockDate;
private SntpService sntpService;
private Date mockDate;
@Before
public void setup() throws IOException {
cohortService = mock(CohortService.class);
lastSyncTimeService = mock(LastSyncTimeService.class);
sntpService = mock(SntpService.class);
controller = new CohortController(cohortService, lastSyncTimeService, sntpService);
lastSyncTime = mock(LastSyncTime.class);
anotherMockDate = mock(Date.class);
mockDate = mock(Date.class);
}
@Test
public void getAllCohorts_shouldReturnAllAvailableCohorts() throws IOException, ParseException, CohortController.CohortFetchException {
List<Cohort> cohorts = new ArrayList<Cohort>();
when(cohortService.getAllCohorts()).thenReturn(cohorts);
assertThat(controller.getAllCohorts(), is(cohorts));
}
@Test(expected = CohortController.CohortFetchException.class)
public void getAllCohorts_shouldThrowCohortFetchExceptionIfExceptionThrownByCohortService() throws IOException, ParseException, CohortController.CohortFetchException {
doThrow(new IOException()).when(cohortService).getAllCohorts();
controller.getAllCohorts();
doThrow(new ParseException()).when(cohortService).getAllCohorts();
controller.getAllCohorts();
}
@Test
public void downloadAllCohorts_shouldReturnDownloadedCohorts() throws CohortController.CohortDownloadException, IOException {
List<Cohort> downloadedCohorts = new ArrayList<Cohort>();
when(cohortService.downloadCohortsByName(StringUtils.EMPTY)).thenReturn(downloadedCohorts);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS)).thenReturn(null);
controller.downloadAllCohorts();
assertThat(controller.downloadAllCohorts(), is(downloadedCohorts));
}
@Test(expected = CohortController.CohortDownloadException.class)
public void downloadAllCohorts_shouldThrowCohortDownloadExceptionIfExceptionIsThrownByCohortService() throws CohortController.CohortDownloadException, IOException {
doThrow(new IOException()).when(cohortService).downloadCohortsByNameAndSyncDate(StringUtils.EMPTY, null);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS)).thenReturn(null);
controller.downloadAllCohorts();
}
@Test
public void shouldSaveLastSyncTimeAfterDownloadingAllCohorts() throws Exception, CohortController.CohortDownloadException {
ArgumentCaptor<LastSyncTime> lastSyncCaptor = ArgumentCaptor.forClass(LastSyncTime.class);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS)).thenReturn(anotherMockDate);
when(sntpService.getLocalTime()).thenReturn(mockDate);
controller.downloadAllCohorts();
verify(lastSyncTimeService).saveLastSyncTime(lastSyncCaptor.capture());
verify(lastSyncTimeService).getLastSyncTimeFor(DOWNLOAD_COHORTS);
LastSyncTime setLastSyncTime = lastSyncCaptor.getValue();
assertThat(setLastSyncTime.getApiName(), is(DOWNLOAD_COHORTS));
assertThat(setLastSyncTime.getLastSyncDate(), is(mockDate));
assertThat(setLastSyncTime.getParamSignature(), nullValue());
}
@Test
public void shouldSaveLastSyncTimeAfterDownloadingAllCohortsWithPrefix() throws Exception, CohortController.CohortDownloadException {
ArgumentCaptor<LastSyncTime> lastSyncCaptor = ArgumentCaptor.forClass(LastSyncTime.class);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS, "prefix1")).thenReturn(anotherMockDate);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS, "prefix2")).thenReturn(anotherMockDate);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS)).thenReturn(anotherMockDate);
when(sntpService.getLocalTime()).thenReturn(mockDate);
controller.downloadCohortsByPrefix(asList(new String[]{"prefix1", "prefix2"}));
verify(lastSyncTimeService, times(2)).saveLastSyncTime(lastSyncCaptor.capture());
verify(lastSyncTimeService).getLastSyncTimeFor(DOWNLOAD_COHORTS, "prefix1");
verify(lastSyncTimeService).getLastSyncTimeFor(DOWNLOAD_COHORTS, "prefix2");
LastSyncTime firstSetLastSyncTime = lastSyncCaptor.getAllValues().get(0);
LastSyncTime secondSetLastSyncTime = lastSyncCaptor.getAllValues().get(1);
assertThat(firstSetLastSyncTime.getApiName(), is(DOWNLOAD_COHORTS));
assertThat(firstSetLastSyncTime.getLastSyncDate(), is(mockDate));
assertThat(firstSetLastSyncTime.getParamSignature(), is("prefix1"));
assertThat(secondSetLastSyncTime.getApiName(), is(DOWNLOAD_COHORTS));
assertThat(secondSetLastSyncTime.getLastSyncDate(), is(mockDate));
assertThat(secondSetLastSyncTime.getParamSignature(), is("prefix2"));
}
@Test
public void downloadCohortDataByUuid_shouldDownloadCohortByUuid() throws IOException, CohortController.CohortDownloadException {
CohortData cohortData = new CohortData();
String uuid = "uuid";
when(cohortService.downloadCohortDataAndSyncDate(uuid, false, null)).thenReturn(cohortData);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS_DATA, uuid)).thenReturn(null);
assertThat(controller.downloadCohortDataByUuid(uuid), is(cohortData));
}
@Test
public void shouldGetLastSynchDateAndUseItWhenDownloadingData() throws IOException, CohortController.CohortDownloadException {
CohortData cohortData = mock(CohortData.class);
String uuid = "uuid";
when(cohortService.downloadCohortData(uuid, false)).thenReturn(cohortData);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS_DATA, uuid)).thenReturn(mockDate);
when(cohortService.downloadCohortDataAndSyncDate(uuid, false, mockDate)).thenReturn(cohortData);
controller.downloadCohortDataByUuid(uuid);
verify(lastSyncTimeService).getLastSyncTimeFor(DOWNLOAD_COHORTS_DATA, uuid);
verify(cohortService,never()).downloadCohortData(uuid, false);
}
@Test
public void shouldSaveLastSyncTimeOfCohortData() throws Exception, CohortController.CohortDownloadException {
String uuid = "uuid";
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS_DATA, uuid)).thenReturn(mockDate);
when(sntpService.getLocalTime()).thenReturn(anotherMockDate);
controller.downloadCohortDataByUuid(uuid);
ArgumentCaptor<LastSyncTime> captor = ArgumentCaptor.forClass(LastSyncTime.class);
verify(lastSyncTimeService).saveLastSyncTime(captor.capture());
LastSyncTime savedLastSyncTime = captor.getValue();
assertThat(savedLastSyncTime.getApiName(), is(DOWNLOAD_COHORTS_DATA));
assertThat(savedLastSyncTime.getLastSyncDate(), is(anotherMockDate));
assertThat(savedLastSyncTime.getParamSignature(), is(uuid));
}
@Test(expected = CohortController.CohortDownloadException.class)
public void downloadCohortDataByUuid_shouldThrowCohortDownloadExceptionIfExceptionThrownByCohortService() throws IOException, CohortController.CohortDownloadException {
String uuid = "uuid";
doThrow(new IOException()).when(cohortService).downloadCohortDataAndSyncDate(uuid, false, null);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS_DATA, uuid)).thenReturn(null);
controller.downloadCohortDataByUuid(uuid);
}
@Test
public void downloadFormTemplates_shouldDownloadAllFormTemplates() throws IOException, CohortController.CohortDownloadException {
String[] uuids = new String[]{"uuid1", "uuid2"};
CohortData cohortData1 = new CohortData();
CohortData cohortData2 = new CohortData();
when(cohortService.downloadCohortDataAndSyncDate(uuids[0], false, null)).thenReturn(cohortData1);
when(cohortService.downloadCohortDataAndSyncDate(uuids[1], false, null)).thenReturn(cohortData2);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS_DATA, "uuid1")).thenReturn(null);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS_DATA, "uuid2")).thenReturn(null);
List<CohortData> allCohortData = controller.downloadCohortData(uuids);
assertThat(allCohortData.size(), is(2));
assertThat(allCohortData, hasItem(cohortData1));
assertThat(allCohortData, hasItem(cohortData2));
}
@Test
public void downloadCohortsByPrefix_shouldDownloadAllCohortsForTheGivenPrefixes() throws IOException, CohortController.CohortDownloadException {
List<String> cohortPrefixes = new ArrayList<String>() {{
add("Age");
add("age");
add("Encounter");
}};
Cohort cohort11 = new Cohort() {{
setUuid("uuid1");
setName("Age between 20 and 30");
}};
Cohort cohort12 = new Cohort() {{
setUuid("uuid1");
setName("Age between 20 and 30");
}};
Cohort cohort2 = new Cohort() {{
setUuid("uuid2");
setName("Patients with age over 65");
}};
Cohort cohort3 = new Cohort() {{
setUuid("uuid3");
setName("Encounter 1");
}};
Cohort cohort4 = new Cohort() {{
setUuid("uuid4");
setName("Encounter 2");
}};
ArrayList<Cohort> agePrefixedCohortList1 = new ArrayList<Cohort>();
agePrefixedCohortList1.add(cohort11);
agePrefixedCohortList1.add(cohort2);
ArrayList<Cohort> agePrefixedCohortList2 = new ArrayList<Cohort>();
agePrefixedCohortList2.add(cohort12);
agePrefixedCohortList2.add(cohort2);
ArrayList<Cohort> encounterPerfixedCohortList = new ArrayList<Cohort>();
encounterPerfixedCohortList.add(cohort3);
encounterPerfixedCohortList.add(cohort4);
when(cohortService.downloadCohortsByNameAndSyncDate(cohortPrefixes.get(0), mockDate)).thenReturn(agePrefixedCohortList1);
when(cohortService.downloadCohortsByNameAndSyncDate(cohortPrefixes.get(1), anotherMockDate)).thenReturn(agePrefixedCohortList2);
when(cohortService.downloadCohortsByNameAndSyncDate(cohortPrefixes.get(2), anotherMockDate)).thenReturn(encounterPerfixedCohortList);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS, cohortPrefixes.get(0))).thenReturn(anotherMockDate);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS, cohortPrefixes.get(1))).thenReturn(anotherMockDate);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS, cohortPrefixes.get(2))).thenReturn(anotherMockDate);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_COHORTS)).thenReturn(anotherMockDate);
when(sntpService.getLocalTime()).thenReturn(mockDate);
List<Cohort> downloadedCohorts = controller.downloadCohortsByPrefix(cohortPrefixes);
assertThat(downloadedCohorts.size(), is(3));
assertTrue(downloadedCohorts.contains(cohort11));
assertTrue(downloadedCohorts.contains(cohort3));
assertTrue(downloadedCohorts.contains(cohort4));
}
@Test
public void saveAllCohorts_shouldSaveAllCohorts() throws CohortController.CohortSaveException, IOException {
ArrayList<Cohort> cohorts = new ArrayList<Cohort>() {{
add(new Cohort());
add(new Cohort());
add(new Cohort());
}};
controller.saveAllCohorts(cohorts);
verify(cohortService).saveCohorts(cohorts);
verifyNoMoreInteractions(cohortService);
}
@Test(expected = CohortController.CohortSaveException.class)
public void saveAllCohorts_shouldThrowCohortSaveExceptionIfExceptionThrownByCohortService() throws IOException, ParseException, CohortController.CohortSaveException {
ArrayList<Cohort> cohorts = new ArrayList<Cohort>() {{
add(new Cohort());
}};
doThrow(new IOException()).when(cohortService).saveCohorts(cohorts);
controller.saveAllCohorts(cohorts);
}
@Test
public void deleteAllCohorts_shouldDeleteAllCohorts() throws IOException, ParseException, CohortController.CohortDeleteException {
ArrayList<Cohort> cohorts = new ArrayList<Cohort>() {{
add(new Cohort());
add(new Cohort());
}};
when(cohortService.getAllCohorts()).thenReturn(cohorts);
controller.deleteAllCohorts();
verify(cohortService).getAllCohorts();
verify(cohortService).deleteCohorts(cohorts);
verifyNoMoreInteractions(cohortService);
}
@Test(expected = CohortController.CohortDeleteException.class)
public void deleteAllCohorts_shouldThrowCohortSaveExceptionIfExceptionThrownByCohortService() throws IOException, ParseException, CohortController.CohortDeleteException {
ArrayList<Cohort> cohorts = new ArrayList<Cohort>() {{
add(new Cohort());
add(new Cohort());
}};
when(cohortService.getAllCohorts()).thenReturn(cohorts);
doThrow(new IOException()).when(cohortService).deleteCohorts(cohorts);
controller.deleteAllCohorts();
}
@Test
public void getTotalCohortsCount_shouldReturnEmptyListOfNoCohortsHaveBeenSynced() throws IOException, ParseException, CohortController.CohortFetchException {
when(cohortService.countAllCohorts()).thenReturn(2);
assertThat(controller.countAllCohorts(), is(2));
}
@Test
public void getSyncedCohortsCount_shouldReturnTotalNumberOfSyncedCohorts() throws IOException, ParseException, CohortController.CohortFetchException {
List<Cohort> cohorts = new ArrayList<Cohort>();
cohorts.add(new Cohort());
when(cohortService.getAllCohorts()).thenReturn(cohorts);
when(cohortService.countCohortMembers(anyString())).thenReturn(2);
assertThat(controller.countSyncedCohorts(), is(1));
}
@Test
public void getSyncedCohortsCount_shouldReturnZeroIfNoCohortIsSynced() throws IOException, ParseException, CohortController.CohortFetchException {
List<Cohort> cohorts = new ArrayList<Cohort>();
when(cohortService.getAllCohorts()).thenReturn(cohorts);
assertThat(controller.countSyncedCohorts(), is(0));
}
@Test
public void getSyncedCohorts_shouldReturnTheCohortsWhichHaveMoreThanOneMember() throws CohortController.CohortReplaceException, IOException, ParseException, CohortController.CohortFetchException {
Cohort cohort = new Cohort();
when(cohortService.getAllCohorts()).thenReturn(asList(cohort));
when(cohortService.countCohortMembers(anyString())).thenReturn(1);
assertThat(controller.getSyncedCohorts(), hasItem(cohort));
}
@Test
public void getSyncedCohorts_shouldNotReturnCohortsIfTheyHaveNoMembers() throws CohortController.CohortReplaceException, IOException, ParseException, CohortController.CohortFetchException {
Cohort cohort = new Cohort();
when(cohortService.getAllCohorts()).thenReturn(asList(cohort));
when(cohortService.countCohortMembers(anyString())).thenReturn(0);
assertThat(controller.getSyncedCohorts().size(), is(0));
}
}