/*
* 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.Concept;
import com.muzima.api.model.LastSyncTime;
import com.muzima.api.model.Observation;
import com.muzima.api.service.ConceptService;
import com.muzima.api.service.EncounterService;
import com.muzima.api.service.LastSyncTimeService;
import com.muzima.api.service.ObservationService;
import com.muzima.model.observation.ConceptWithObservations;
import com.muzima.service.SntpService;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import static com.muzima.api.model.APIName.DOWNLOAD_OBSERVATIONS;
import static java.util.Arrays.asList;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.hasItems;
import static org.mockito.Matchers.anyList;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class ObservationControllerTest {
private ObservationController observationController;
private ObservationService observationService;
private ConceptService conceptService;
private LastSyncTimeService lastSyncTimeService;
private SntpService sntpService;
@Before
public void setUp() throws Exception {
observationService = mock(ObservationService.class);
conceptService = mock(ConceptService.class);
EncounterService encounterService = mock(EncounterService.class);
lastSyncTimeService = mock(LastSyncTimeService.class);
sntpService = mock(SntpService.class);
observationController = new ObservationController(observationService, conceptService,
encounterService, lastSyncTimeService, sntpService);
}
@Test
public void shouldCheckLastSyncTimeBeforeDownloadingObservations() throws Exception, ObservationController.DownloadObservationException {
List<String> patientUuids = asList("PatientUuid1", "PatientUuid2");
List<String> conceptUuids = asList("ConceptUuid1", "ConceptUuid2");
Date aDate = mock(Date.class);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_OBSERVATIONS, "PatientUuid1,PatientUuid2;ConceptUuid1,ConceptUuid2")).thenReturn(aDate);
observationController.downloadObservationsByPatientUuidsAndConceptUuids(patientUuids, conceptUuids);
verify(lastSyncTimeService).getLastSyncTimeFor(DOWNLOAD_OBSERVATIONS, "PatientUuid1,PatientUuid2;ConceptUuid1,ConceptUuid2");
verify(lastSyncTimeService, never()).getFullLastSyncTimeInfoFor(DOWNLOAD_OBSERVATIONS);
}
@Test
public void shouldUseLastSyncTimeToDownloadObservations() throws Exception, ObservationController.DownloadObservationException {
List<String> patientUuids = asList("PatientUuid1", "PatientUuid2");
List<String> conceptUuids = asList("ConceptUuid1", "ConceptUuid2");
Date lastSyncTime = mock(Date.class);
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_OBSERVATIONS, "PatientUuid1,PatientUuid2;ConceptUuid1,ConceptUuid2")).thenReturn(lastSyncTime);
observationController.downloadObservationsByPatientUuidsAndConceptUuids(patientUuids, conceptUuids);
verify(observationService, never()).downloadObservationsByPatientUuidsAndConceptUuids(anyList(), anyList());
verify(observationService).downloadObservations(patientUuids, conceptUuids, lastSyncTime);
}
@Test
public void shouldUpdateLastSyncTimeForObservation() throws Exception, ObservationController.DownloadObservationException {
List<String> patientUuids = asList("PatientUuid1", "PatientUuid2");
List<String> conceptUuids = asList("ConceptUuid1", "ConceptUuid2");
Date currentDate = mock(Date.class);
when(sntpService.getLocalTime()).thenReturn(currentDate);
observationController.downloadObservationsByPatientUuidsAndConceptUuids(patientUuids, conceptUuids);
ArgumentCaptor<LastSyncTime> argumentCaptor = ArgumentCaptor.forClass(LastSyncTime.class);
verify(lastSyncTimeService).saveLastSyncTime(argumentCaptor.capture());
LastSyncTime savedLastSyncTime = argumentCaptor.getValue();
assertThat(savedLastSyncTime.getApiName(), is(DOWNLOAD_OBSERVATIONS));
assertThat(savedLastSyncTime.getLastSyncDate(), is(currentDate));
assertThat(savedLastSyncTime.getParamSignature(), is("PatientUuid1,PatientUuid2;ConceptUuid1,ConceptUuid2"));
}
@Test
public void shouldProperlyProcessChangeInKnownPatientOrConcept() throws ObservationController.DownloadObservationException, IOException {
List<String> patientUuids = asList("PatientUuid1", "PatientUuid2");
List<String> conceptUuids = asList("ConceptUuid1", "ConceptUuid2");
List<String> previousPatientUuids = asList("PatientUuid1", "PatientUuid3");
List<String> previousConceptUuids = asList("ConceptUuid1", "ConceptUuid3");
List<String> newPatientUuids = Collections.singletonList("PatientUuid2");
List<String> newConceptUuids = Collections.singletonList("ConceptUuid2");
LastSyncTime lastSyncTimeInFull = mock(LastSyncTime.class);
when(lastSyncTimeInFull.getParamSignature()).thenReturn("PatientUuid1,PatientUuid3;ConceptUuid1,ConceptUuid3");
Date aDate = mock(Date.class);
when(lastSyncTimeInFull.getLastSyncDate()).thenReturn(aDate);
when(lastSyncTimeService.getFullLastSyncTimeInfoFor(DOWNLOAD_OBSERVATIONS)).thenReturn(lastSyncTimeInFull);
List<Observation> anObservationSet = new ArrayList<>();
Observation anObservation = mock(Observation.class);
anObservationSet.add(anObservation);
when(observationService.downloadObservations(previousPatientUuids, previousConceptUuids, aDate)).thenReturn(anObservationSet);
List<Observation> anotherObservationSet = new ArrayList<>();
Observation anotherObservation = mock(Observation.class);
anotherObservationSet.add(anotherObservation);
List<String> allConceptUuids = new ArrayList<>();
allConceptUuids.addAll(previousConceptUuids);
allConceptUuids.addAll(newConceptUuids);
Collections.sort(allConceptUuids);
when(observationService.downloadObservations(newPatientUuids, allConceptUuids, null)).thenReturn(anotherObservationSet);
Date currentDate = mock(Date.class);
when(sntpService.getLocalTime()).thenReturn(currentDate);
List<Observation> observations = observationController.downloadObservationsByPatientUuidsAndConceptUuids(patientUuids, conceptUuids);
verify(lastSyncTimeService).getFullLastSyncTimeInfoFor(DOWNLOAD_OBSERVATIONS);
verify(observationService).downloadObservations(previousPatientUuids, previousConceptUuids, aDate);
verify(observationService).downloadObservations(previousPatientUuids, newConceptUuids, null);
verify(observationService).downloadObservations(newPatientUuids, allConceptUuids, null);
assertThat(observations.size(), is(2));
assertThat(observations, hasItems(anObservation, anotherObservation));
ArgumentCaptor<LastSyncTime> argumentCaptor = ArgumentCaptor.forClass(LastSyncTime.class);
verify(lastSyncTimeService).saveLastSyncTime(argumentCaptor.capture());
LastSyncTime savedLastSyncTime = argumentCaptor.getValue();
assertThat(savedLastSyncTime.getApiName(), is(DOWNLOAD_OBSERVATIONS));
assertThat(savedLastSyncTime.getLastSyncDate(), is(currentDate));
assertThat(savedLastSyncTime.getParamSignature(), is("PatientUuid1,PatientUuid2,PatientUuid3;ConceptUuid1,ConceptUuid2,ConceptUuid3"));
}
@Test
public void shouldRecognisedNonInitialisedLastSyncTime() throws ObservationController.DownloadObservationException, IOException {
List<String> patientUuids = asList("PatientUuid1", "PatientUuid2");
List<String> conceptUuids = asList("ConceptUuid1", "ConceptUuid2");
when(lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_OBSERVATIONS, "PatientUuid1,PatientUuid2;ConceptUuid1,ConceptUuid2")).thenReturn(null);
when(lastSyncTimeService.getFullLastSyncTimeInfoFor(DOWNLOAD_OBSERVATIONS)).thenReturn(null);
observationController.downloadObservationsByPatientUuidsAndConceptUuids(patientUuids, conceptUuids);
verify(observationService).downloadObservations(patientUuids, conceptUuids, null);
}
@Test
public void getConceptWithObservations_shouldReturnConceptsWithObservations() throws Exception, ObservationController.LoadObservationException {
final Concept concept1 = new Concept() {{
setUuid("concept1");
}};
final Concept concept2 = new Concept() {{
setUuid("concept2");
}};
final List<Observation> observations = buildObservations(concept1, concept2);
String patientUuid = "patientUuid";
when(observationService.getObservationsByPatient(patientUuid)).thenReturn(observations);
when(conceptService.getConceptByUuid("concept1")).thenReturn(concept1);
when(conceptService.getConceptByUuid("concept2")).thenReturn(concept2);
List<ConceptWithObservations> result = observationController.getConceptWithObservations(patientUuid);
assertThat(result.size(), is(2));
assertThat(result.get(0).getConcept().getUuid(), is("concept1"));
assertThat(result.get(1).getConcept().getUuid(), is("concept2"));
ConceptWithObservations conceptWithObservations1 = result.get(0);
ConceptWithObservations conceptWithObservations2 = result.get(1);
assertThat(conceptWithObservations1.getObservations().size(), is(3));
assertThat(conceptWithObservations2.getObservations().size(), is(1));
}
@Test
public void getConceptWithObservations_shouldReturnConceptsWithSortedObservations() throws Exception, ObservationController.LoadObservationException {
final Concept concept1 = new Concept() {{
setUuid("concept1");
}};
final Concept concept2 = new Concept() {{
setUuid("concept2");
}};
final List<Observation> observations = buildObservations(concept1, concept2);
String patientUuid = "patientUuid";
when(observationService.getObservationsByPatient(patientUuid)).thenReturn(observations);
when(conceptService.getConceptByUuid("concept1")).thenReturn(concept1);
when(conceptService.getConceptByUuid("concept2")).thenReturn(concept2);
List<ConceptWithObservations> result = observationController.getConceptWithObservations(patientUuid);
ConceptWithObservations conceptWithObservations1 = result.get(0);
assertThat(conceptWithObservations1.getObservations().get(0), is(observations.get(2)));
assertThat(conceptWithObservations1.getObservations().get(1), is(observations.get(3)));
assertThat(conceptWithObservations1.getObservations().get(2), is(observations.get(0)));
}
@Test
public void saveObservations_shouldSaveObservationsForPatient() throws Exception, ObservationController.SaveObservationException {
final Concept concept1 = new Concept() {{
setUuid("concept1");
}};
final Concept concept2 = new Concept() {{
setUuid("concept2");
}};
final List<Observation> observations = buildObservations(concept1, concept2);
observationController.saveObservations(observations);
verify(observationService).saveObservations(observations);
}
private List<Observation> buildObservations(final Concept concept1, final Concept concept2) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
final Date date1 = sdf.parse("21/12/2012");
final Date date2 = sdf.parse("25/12/2012");
final Date date3 = sdf.parse("09/04/2013");
ArrayList<Observation> observations = new ArrayList<>();
final Observation ob1 = new Observation() {{
setUuid("ob1");
setConcept(concept1);
setObservationDatetime(date1);
}};
final Observation ob2 = new Observation() {{
setUuid("ob2");
setConcept(concept2);
setObservationDatetime(date2);
}};
final Observation ob3 = new Observation() {{
setUuid("ob3");
setConcept(concept1);
setObservationDatetime(date3);
}};
final Observation ob4 = new Observation() {{
setUuid("ob4");
setConcept(concept1);
setObservationDatetime(date2);
}};
observations.add(ob1);
observations.add(ob2);
observations.add(ob3);
observations.add(ob4);
return observations;
}
}