package net.frontlinesms.csv; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import thinlet.Thinlet; import net.frontlinesms.data.domain.Contact; import net.frontlinesms.data.domain.Group; import net.frontlinesms.data.repository.GroupMembershipDao; import net.frontlinesms.junit.BaseTestCase; import net.frontlinesms.ui.i18n.ClasspathLanguageBundle; import net.frontlinesms.ui.i18n.LanguageBundle; import static org.mockito.Mockito.*; /** * Test class for {@link CsvExporter} * @author Alex */ public class CsvExportTests extends BaseTestCase { //> STATIC CONSTANTS /** Default row format used in {@link #testContactExport()}. N.B. This will have to be kept up-to-date if there * is a change to how the export works in the UI, as this may change the export order. * @return default row format for exporting contacts */ private static final CsvRowFormat getContactExportRowFormat() { CsvRowFormat rowFormat = new CsvRowFormat(); rowFormat.addMarker(CsvUtils.MARKER_CONTACT_NAME); rowFormat.addMarker(CsvUtils.MARKER_CONTACT_PHONE); rowFormat.addMarker(CsvUtils.MARKER_CONTACT_OTHER_PHONE); rowFormat.addMarker(CsvUtils.MARKER_CONTACT_EMAIL); rowFormat.addMarker(CsvUtils.MARKER_CONTACT_STATUS); rowFormat.addMarker(CsvUtils.MARKER_CONTACT_NOTES); rowFormat.addMarker(CsvUtils.MARKER_CONTACT_GROUPS); return rowFormat; } //> TEST METHODS /** * Test {@link CsvExporter#exportContacts(File, List, CsvRowFormat)}. * @throws IOException If there was an unexpected error writing or reading to a file */ public void testContactExport() throws IOException { // Export a number of contacts to a file, and check that the generated file is as expected. ArrayList<Contact> contacts = new ArrayList<Contact>(); contacts.add(new Contact("Test Number", "000", "", "", "", true)); contacts.add(new Contact("\u0634\u0626\u0647\u0629", "07890123456", "0987654321", "azim@mo.jo", "", false)); contacts.add(new Contact("Sly Eddie", "01234567890", "554466221133", "sly.eddie@ramprakash.co.uk", "Sly Eddie is a sneaky chap.", true)); contacts.add(new Contact("Richard E. Grant", "+44852774", "+1800-RICH-ARDE", "", "\"What a piece of work is a man!\"", true)); // Make sure the English i18n bundle is available to provision the export column names LanguageBundle englishBundle = ClasspathLanguageBundle.create("/resources/languages/frontlineSMS.properties"); Thinlet.DEFAULT_ENGLISH_BUNDLE = englishBundle.getProperties(); File generatedFile = super.getOutputFile(this.getClass().getSimpleName() + ".contacts.csv"); // Make a mock groupMembershipDao which will return NO GROUPS for any contact GroupMembershipDao emptyGroupMembershipDao = mock(GroupMembershipDao.class); List<Group> emptyGroupList = Collections.emptyList(); when(emptyGroupMembershipDao.getGroups(any(Contact.class))).thenReturn(emptyGroupList); CsvExporter.exportContacts(generatedFile, contacts, emptyGroupMembershipDao, getContactExportRowFormat()); assertEquals("Generated CSV file did not contain the expected values.", this.getClass().getResourceAsStream(this.getClass().getSimpleName() + ".contacts.csv"), new FileInputStream(generatedFile)); } /** * Test {@link CsvUtils#escapeValue(String)} * TODO move this to CsvUtilsTest class */ public void testCsvEscape() { testCsvEscaped("one", "one", "\"one\""); testCsvEscaped("on\"e", "\"on\"\"e\""); testCsvEscaped("column0\tcolumn1", "column0\tcolumn1", "\"column0\tcolumn1\""); testCsvEscaped("line0\rline1", "\"line0\rline1\""); } //> STATIC HELPER METHODS /** * Internal test method for {@link #testCsvEscape()} * @param unescaped * @param acceptedEscaped */ private static void testCsvEscaped(String unescaped, String... acceptedEscaped) { String escaped = CsvUtils.escapeValue(unescaped); for(String expectedEscaped : acceptedEscaped) { if(escaped.equals(expectedEscaped)) return; } throw new IllegalArgumentException("Expected result not achieved:" + "\nunescaped: " + unescaped + "\nescaped : " + escaped + "\naccepted : " + toString(acceptedEscaped)); } /** * Convert an array of {@link String}s into a comma-separated list of {@link String}s. * @param strings * @return A list of the strings provided in the array separated by commas and surrounded by curly braces */ private static final String toString(String[] strings) { String ret = "{"; for(String s : strings) { ret += s + ", "; } return ret.substring(0, ret.length()-2) + "}"; } }