package co.smartreceipts.android.filters; import android.content.Context; import org.json.JSONException; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import java.sql.Date; import java.util.ArrayList; import java.util.TimeZone; import co.smartreceipts.android.model.Receipt; import co.smartreceipts.android.utils.ReceiptUtils; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @RunWith(RobolectricTestRunner.class) public class ReceiptFilterTest { // Test constants for Price checking private static final String PRICE_NORMAL = "100.00"; private static final String PRICE_HIGH = "150.00"; private static final String PRICE_LOW = "50.00"; // Test constants for Date checking private static final TimeZone TZ = ReceiptUtils.Constants.TIMEZONE; private static final long MILLIS = new java.util.Date().getTime(); private static final Date NOW = new Date(MILLIS); private static final Date FUTURE = new Date(MILLIS + 1000); private static final Date PAST = new Date(MILLIS - 1000); private Context context; @Before public void setUp() { context = RuntimeEnvironment.application; } @Test public void receiptCategoryFilterTest() throws JSONException { final Receipt receipt1 = ReceiptUtils.newDefaultReceiptBuilderFactory(context).build(); final Receipt receipt2 = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setCategory("BAD Category").build(); final ReceiptCategoryFilter filter = new ReceiptCategoryFilter(ReceiptUtils.Constants.CATEGORY.getName()); assertTrue(filter.accept(receipt1)); assertFalse(filter.accept(receipt2)); assertEquals(filter, FilterFactory.getReceiptFilter(filter.getJsonRepresentation())); // Confirm we can properly recreate assertEquals(filter.getNameResource(), co.smartreceipts.android.R.string.filter_name_receipt_category); assertEquals(filter.getType(), FilterType.String); } @Test public void receiptIsReimbursableFilterTest() throws JSONException { final Receipt receipt1 = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setIsReimbursable(true).build(); final Receipt receipt2 = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setIsReimbursable(false).build(); final ReceiptIsReimbursableFilter filter = new ReceiptIsReimbursableFilter(); assertTrue(filter.accept(receipt1)); assertFalse(filter.accept(receipt2)); assertEquals(filter, FilterFactory.getReceiptFilter(filter.getJsonRepresentation())); assertEquals(filter.getNameResource(), co.smartreceipts.android.R.string.filter_name_receipt_reimbursable); assertEquals(filter.getType(), FilterType.Boolean); } @Test public void receiptIsSelectedFilterTest() throws JSONException { final Receipt receipt1 = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setIsSelected(true).build(); final Receipt receipt2 = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setIsSelected(false).build(); final ReceiptSelectedFilter filter = new ReceiptSelectedFilter(); assertTrue(filter.accept(receipt1)); assertFalse(filter.accept(receipt2)); assertEquals(filter, FilterFactory.getReceiptFilter(filter.getJsonRepresentation())); assertEquals(filter.getNameResource(), co.smartreceipts.android.R.string.filter_name_receipt_selected); assertEquals(filter.getType(), FilterType.Boolean); } @Test public void receiptMinimumPriceFilterTest() throws JSONException { final Receipt receiptNormal = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setPrice(PRICE_NORMAL).build(); final Receipt receiptHigh = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setPrice(PRICE_HIGH).build(); final Receipt receiptLow = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setPrice(PRICE_LOW).build(); final ReceiptMinimumPriceFilter filter = new ReceiptMinimumPriceFilter( Float.parseFloat(PRICE_NORMAL), ReceiptUtils.Constants.CURRENCY_CODE); assertTrue(filter.accept(receiptNormal)); assertTrue(filter.accept(receiptHigh)); assertFalse(filter.accept(receiptLow)); assertEquals(filter, FilterFactory.getReceiptFilter(filter.getJsonRepresentation())); assertEquals(filter.getNameResource(), co.smartreceipts.android.R.string.filter_name_receipt_min_price); assertEquals(filter.getType(), FilterType.Float); } @Test public void receiptMaximumPriceFilterTest() throws JSONException { final Receipt receiptNormal = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setPrice(PRICE_NORMAL).build(); final Receipt receiptHigh = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setPrice(PRICE_HIGH).build(); final Receipt receiptLow = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setPrice(PRICE_LOW).build(); final ReceiptMaximumPriceFilter filter = new ReceiptMaximumPriceFilter( Float.parseFloat(PRICE_NORMAL), ReceiptUtils.Constants.CURRENCY_CODE); assertTrue(filter.accept(receiptNormal)); assertFalse(filter.accept(receiptHigh)); assertTrue(filter.accept(receiptLow)); assertEquals(filter, FilterFactory.getReceiptFilter(filter.getJsonRepresentation())); assertEquals(filter.getNameResource(), co.smartreceipts.android.R.string.filter_name_receipt_max_price); assertEquals(filter.getType(), FilterType.Float); } @Test public void receiptOnOrAfterDayFilterTest() throws JSONException { final Receipt receiptNow = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setDate(NOW).build(); final Receipt receiptFuture = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setDate(FUTURE).build(); final Receipt receiptPast = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setDate(PAST).build(); final ReceiptOnOrAfterDayFilter filter = new ReceiptOnOrAfterDayFilter(NOW, TZ); assertTrue(filter.accept(receiptNow)); assertTrue(filter.accept(receiptFuture)); assertFalse(filter.accept(receiptPast)); assertEquals(filter, FilterFactory.getReceiptFilter(filter.getJsonRepresentation())); assertEquals(filter.getNameResource(), co.smartreceipts.android.R.string.filter_name_receipt_on_or_after); assertEquals(filter.getType(), FilterType.Date); } @Test public void receiptOnOrBeforeDayFilterTest() throws JSONException { final Receipt receiptNow = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setDate(NOW).build(); final Receipt receiptFuture = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setDate(FUTURE).build(); final Receipt receiptPast = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setDate(PAST).build(); final ReceiptOnOrBeforeDayFilter filter = new ReceiptOnOrBeforeDayFilter(NOW, TZ); assertTrue(filter.accept(receiptNow)); assertFalse(filter.accept(receiptFuture)); assertTrue(filter.accept(receiptPast)); assertEquals(filter, FilterFactory.getReceiptFilter(filter.getJsonRepresentation())); assertEquals(filter.getNameResource(), co.smartreceipts.android.R.string.filter_name_receipt_on_or_before); assertEquals(filter.getType(), FilterType.Date); } @Test public void receiptOrFilterTest() throws JSONException { final String category2 = "cat2"; final Receipt receipt1 = ReceiptUtils.newDefaultReceiptBuilderFactory(context).build(); final Receipt receipt2 = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setCategory(category2).build(); final Receipt receipt3 = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setCategory("BAD Category").build(); final ReceiptCategoryFilter filter1 = new ReceiptCategoryFilter(ReceiptUtils.Constants.CATEGORY.getName()); final ReceiptCategoryFilter filter2 = new ReceiptCategoryFilter(category2); final ReceiptOrFilter orFilter = new ReceiptOrFilter(); orFilter.or(filter1); orFilter.or(filter2); assertTrue(orFilter.accept(receipt1)); assertTrue(orFilter.accept(receipt2)); assertFalse(orFilter.accept(receipt3)); assertEquals(orFilter, FilterFactory.getReceiptFilter(orFilter.getJsonRepresentation())); // Confirm we can properly recreate assertEquals(orFilter.getNameResource(), co.smartreceipts.android.R.string.filter_name_or); assertEquals(orFilter.getType(), FilterType.Composite); } @Test public void receiptAndFilterTest() throws JSONException { final Receipt receipt = ReceiptUtils.newDefaultReceiptBuilderFactory(context).build(); final ReceiptIsReimbursableFilter trueFilter1 = new ReceiptIsReimbursableFilter(); final ReceiptCategoryFilter trueFilter2 = new ReceiptCategoryFilter(ReceiptUtils.Constants.CATEGORY.getName()); final ReceiptCategoryFilter falseFilter = new ReceiptCategoryFilter("BAD Category"); final ReceiptAndFilter andFilterGood = new ReceiptAndFilter(); final ReceiptAndFilter andFilterBad = new ReceiptAndFilter(); andFilterGood.and(trueFilter1).and(trueFilter2); andFilterBad.and(trueFilter1).and(trueFilter2).and(falseFilter); assertTrue(andFilterGood.accept(receipt)); assertFalse(andFilterBad.accept(receipt)); assertEquals(andFilterGood, FilterFactory.getReceiptFilter(andFilterGood.getJsonRepresentation())); assertEquals(andFilterBad, FilterFactory.getReceiptFilter(andFilterBad.getJsonRepresentation())); assertEquals(andFilterGood.getNameResource(), co.smartreceipts.android.R.string.filter_name_and); assertEquals(andFilterGood.getType(), FilterType.Composite); } @Test public void receiptNotFilterTest() throws JSONException { // in this test scenario, we will only accept receiptHigh // accept rule: NOT (price <= normal) // equivalent to: (price > normal) final Receipt receiptNormal = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setPrice(PRICE_NORMAL).build(); final Receipt receiptHigh = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setPrice(PRICE_HIGH).build(); final Receipt receiptLow = ReceiptUtils.newDefaultReceiptBuilderFactory(context).setPrice(PRICE_LOW).build(); final ReceiptMaximumPriceFilter priceFilter = new ReceiptMaximumPriceFilter(Float.parseFloat(PRICE_NORMAL), ReceiptUtils.Constants.CURRENCY_CODE); final ReceiptNotFilter notFilter = new ReceiptNotFilter(priceFilter); assertFalse(notFilter.accept(receiptNormal)); assertTrue(notFilter.accept(receiptHigh)); // accepted assertFalse(notFilter.accept(receiptLow)); assertEquals(notFilter, FilterFactory.getReceiptFilter(notFilter.getJsonRepresentation())); assertEquals(notFilter.getNameResource(), co.smartreceipts.android.R.string.filter_name_not); assertEquals(notFilter.getType(), FilterType.Composite); } @Test public void receiptOrFilterConstructorTest() throws JSONException { // in this test scenario, // filters constructed with same data but different method should be equal final ReceiptCategoryFilter filter1 = new ReceiptCategoryFilter(ReceiptUtils.Constants.CATEGORY.getName()); final ReceiptCategoryFilter filter2 = new ReceiptCategoryFilter("Just another category"); // filter 1 -- composited filters added in object instantiation (i.e. constructor) final ArrayList<Filter<Receipt>> filters = new ArrayList<>(); filters.add(filter1); filters.add(filter2); final ReceiptOrFilter orFilter1 = new ReceiptOrFilter(filters); // filter 2 -- composited filters added after object instantiation final ReceiptOrFilter orFilter2 = new ReceiptOrFilter(); orFilter2.or(filter1); orFilter2.or(filter2); assertEquals(orFilter1, orFilter2); assertEquals(orFilter1, FilterFactory.getReceiptFilter(orFilter1.getJsonRepresentation())); assertEquals(orFilter2, FilterFactory.getReceiptFilter(orFilter2.getJsonRepresentation())); } @Test public void receiptAndFilterConstructorTest() throws JSONException { // in this test scenario, // filters constructed with same data but different method should be equal final ReceiptCategoryFilter filter1 = new ReceiptCategoryFilter(ReceiptUtils.Constants.CATEGORY.getName()); final ReceiptCategoryFilter filter2 = new ReceiptCategoryFilter("Just another category"); // filter 1 -- composited filters added in object instantiation (i.e. constructor) final ArrayList<Filter<Receipt>> filters = new ArrayList<>(); filters.add(filter1); filters.add(filter2); final ReceiptAndFilter andFilter1 = new ReceiptAndFilter(filters); // filter 2 -- composited filters added after object instantiation final ReceiptAndFilter andFilter2 = new ReceiptAndFilter(); andFilter2.and(filter1); andFilter2.and(filter2); assertEquals(andFilter1, andFilter2); assertEquals(andFilter1, FilterFactory.getReceiptFilter(andFilter1.getJsonRepresentation())); assertEquals(andFilter2, FilterFactory.getReceiptFilter(andFilter2.getJsonRepresentation())); } }