package net.frontlinesms.plugins.forms;
import static org.mockito.Mockito.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.context.ApplicationContext;
import net.frontlinesms.FrontlineSMS;
import net.frontlinesms.data.domain.Contact;
import net.frontlinesms.data.domain.Group;
import net.frontlinesms.data.repository.ContactDao;
import net.frontlinesms.events.EventBus;
import net.frontlinesms.junit.BaseTestCase;
import net.frontlinesms.plugins.PluginInitialisationException;
import net.frontlinesms.plugins.forms.data.domain.Form;
import net.frontlinesms.plugins.forms.data.domain.FormField;
import net.frontlinesms.plugins.forms.data.domain.FormFieldType;
import net.frontlinesms.plugins.forms.data.domain.ResponseValue;
import net.frontlinesms.plugins.forms.data.repository.FormDao;
import net.frontlinesms.plugins.forms.data.repository.FormResponseDao;
import net.frontlinesms.plugins.forms.request.DataSubmissionRequest;
import net.frontlinesms.plugins.forms.request.NewFormRequest;
import net.frontlinesms.plugins.forms.request.SubmittedFormData;
import net.frontlinesms.plugins.forms.response.NewFormsResponse;
public class FormsPluginControllerTest extends BaseTestCase {
private static final String UNREGISTERED_MSISDN = "+44123456879";
private static final String CONTACT_WITH_NO_FORMS_MSISDN = "+44123456870";
private static final Contact CONTACT_WITH_NO_FORMS = new Contact("I have no forms", CONTACT_WITH_NO_FORMS_MSISDN, null, null, null, true);
private static final String CONTACT_INACTIVE_MSISDN = "+44123456871";
private static final Contact CONTACT_INACTIVE = new Contact("I have no forms", CONTACT_WITH_NO_FORMS_MSISDN, null, null, null, false);
private static final String CONTACT_OK_MSISDN = "+44123456872";
private static final Contact CONTACT_OK = new Contact("I'm ok, thank you", CONTACT_OK_MSISDN, null, null, null, false);
private static final Collection<Integer> NO_FORM_IDS = Collections.emptySet();
private static final Collection<Form> COLLECTION_NO_FORMS = Collections.emptySet();
@SuppressWarnings("unchecked")
public void testHandleNewFormRequest() {
FormsPluginController controller = new FormsPluginController();
FormDao formDao = mock(FormDao.class);
controller.setFormsDao(formDao);
when(formDao.getFormsForUser(eq(CONTACT_WITH_NO_FORMS), anyCollection())).thenReturn(COLLECTION_NO_FORMS);
ContactDao contactDao = mock(ContactDao.class);
controller.setContactDao(contactDao);
when(contactDao.getFromMsisdn(UNREGISTERED_MSISDN)).thenReturn(null);
when(contactDao.getFromMsisdn(CONTACT_INACTIVE_MSISDN)).thenReturn(CONTACT_INACTIVE);
when(contactDao.getFromMsisdn(CONTACT_WITH_NO_FORMS_MSISDN)).thenReturn(CONTACT_WITH_NO_FORMS);
NewFormRequest request = new NewFormRequest(NO_FORM_IDS);
NewFormsResponse responseNone = controller.handleNewFormRequest(request, UNREGISTERED_MSISDN);
assertNull("No response should be sent back to an unregistered contact", responseNone);
NewFormsResponse responseInactive = controller.handleNewFormRequest(request, CONTACT_INACTIVE_MSISDN);
assertNull("No response should be sent back to an inactive contact", responseInactive);
NewFormsResponse responseNoForms = controller.handleNewFormRequest(request, CONTACT_WITH_NO_FORMS_MSISDN);
assertEquals("No forms should be sent back to an contact unregistered for this form", 0, responseNoForms.getNewForms().size());
}
public void testHandleDataSubmissionRequest() {
FormsPluginController controller = new FormsPluginController();
Form formOne = createForm(2);
FormDao formDao = mock(FormDao.class);
when(formDao.getFromId(formOne.getFormMobileId())).thenReturn(formOne);
FormResponseDao formResponseDao = mock(FormResponseDao.class);
ContactDao contactDao = mock(ContactDao.class);
when(contactDao.getFromMsisdn(CONTACT_OK_MSISDN)).thenReturn(CONTACT_OK);
controller.setContactDao(contactDao);
controller.setFormsDao(formDao);
controller.setFormResponseDao(formResponseDao);
SubmittedFormData formDataOne = new SubmittedFormData(formOne.getFormMobileId(), 0, createResponseValues(1));
SubmittedFormData formDataTwo = new SubmittedFormData(formOne.getFormMobileId(), 1, createResponseValues(2));
SubmittedFormData formDataThree = new SubmittedFormData(-1, 2, createResponseValues(2));
SubmittedFormData formDataFour = new SubmittedFormData(formOne.getFormMobileId(), 3, createResponseValues(2));
// Test with no data. Response should be empty
Set<SubmittedFormData> submittedFormData = new HashSet<SubmittedFormData>();
DataSubmissionRequest request = new DataSubmissionRequest(submittedFormData);
Collection<SubmittedFormData> submittedData = controller.handleDataSubmissionRequest(request, CONTACT_OK_MSISDN).getSubmittedData();
assertEquals(0, submittedData.size());
// Test with data containing a different number of fields than the form it's pointing on. Response should be empty.
submittedFormData.add(formDataOne);
request = new DataSubmissionRequest(submittedFormData);
assertEquals(0, controller.handleDataSubmissionRequest(request, CONTACT_OK_MSISDN).getSubmittedData().size());
// Test with a good mobile ID and a good number of field. Should now be 1 SubmittedFormData in the Set.
submittedFormData.add(formDataTwo);
request = new DataSubmissionRequest(submittedFormData);
assertEquals(1, controller.handleDataSubmissionRequest(request, CONTACT_OK_MSISDN).getSubmittedData().size());
// Test with a bad mobile ID. Reponse should still contain one and only one SubmittedFormData.
submittedFormData.add(formDataThree);
request = new DataSubmissionRequest(submittedFormData);
assertEquals(1, controller.handleDataSubmissionRequest(request, CONTACT_OK_MSISDN).getSubmittedData().size());
// Test with data containing a different number of fields than the pointed form. Response should be empty.
submittedFormData.add(formDataFour);
request = new DataSubmissionRequest(submittedFormData);
assertEquals(2, controller.handleDataSubmissionRequest(request, CONTACT_OK_MSISDN).getSubmittedData().size());
}
public void testSetHandler() throws Exception {
// Test bad handler name
FormsPluginController controller = new FormsPluginController();
try {
controller.setHandler("does.not.exist");
fail("Should have thrown ClassNotFoundException.");
} catch(ClassNotFoundException ex) { /* expected */ }
}
public void testInit() throws PluginInitialisationException {
// Test that the controller registers itself with the event bus
FormsPluginController controller = new FormsPluginController();
FrontlineSMS mockFrontlineSms = mock(FrontlineSMS.class);
ApplicationContext mockApplicationContext = mock(ApplicationContext.class);
EventBus mockEventBus = mock(EventBus.class);
when(mockApplicationContext.getBean("eventBus")).thenReturn(mockEventBus);
try {
controller.init(mockFrontlineSms , mockApplicationContext);
fail("Should have thrown exception due to missing form handler.");
} catch(PluginInitialisationException ex) { /* expected as no form handler available */ }
verify(mockApplicationContext).getBean("formDao");
verify(mockApplicationContext).getBean("formResponseDao");
}
//> HELPER METHODS
/**
* Create a {@link Form} with a certain number of fields and the given mobileId
* @param numberOfFields
* @param mobileId
* @return The created {@link Form}
*/
private Form createForm(int numberOfFields) {
Form form = new Form("form" + numberOfFields);
for (int i = 0; i < numberOfFields; i++) {
form.addField(new FormField(FormFieldType.CHECK_BOX, "CB" + i));
}
form.setPermittedGroup(new Group(null, null));
return form;
}
private List<ResponseValue> createResponseValues(int nbResponseValues) {
ArrayList<ResponseValue> responseValues = new ArrayList<ResponseValue>();
for (int i = 0; i < nbResponseValues; i++) {
responseValues.add(new ResponseValue("response" + i));
}
return responseValues;
}
}