mirror of
https://github.com/CatimaLoyalty/Android.git
synced 2026-04-02 06:42:47 -04:00
Introduce read-only ContentProvider for cards (#1121)
This commit is contained in:
@@ -67,25 +67,6 @@ public class ImportExportTest {
|
||||
mDatabase = TestHelpers.getEmptyDb(activity).getWritableDatabase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given number of cards, each with
|
||||
* an index in the store name.
|
||||
*
|
||||
* @param cardsToAdd
|
||||
*/
|
||||
private void addLoyaltyCards(int cardsToAdd) {
|
||||
// Add in reverse order to test sorting
|
||||
for (int index = cardsToAdd; index > 0; index--) {
|
||||
String storeName = String.format("store, \"%4d", index);
|
||||
String note = String.format("note, \"%4d", index);
|
||||
long id = DBHelper.insertLoyaltyCard(mDatabase, storeName, note, null, null, new BigDecimal(String.valueOf(index)), null, BARCODE_DATA, null, BARCODE_TYPE, index, 0, null,0);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
assertEquals(cardsToAdd, DBHelper.getLoyaltyCardCount(mDatabase));
|
||||
}
|
||||
|
||||
private void addLoyaltyCardsFiveStarred() {
|
||||
int cardsToAdd = 9;
|
||||
// Add in reverse order to test sorting
|
||||
@@ -183,18 +164,6 @@ public class ImportExportTest {
|
||||
assertEquals(4, DBHelper.getLoyaltyCardCount(mDatabase));
|
||||
}
|
||||
|
||||
private void addGroups(int groupsToAdd) {
|
||||
// Add in reverse order to test sorting
|
||||
for (int index = groupsToAdd; index > 0; index--) {
|
||||
String groupName = String.format("group, \"%4d", index);
|
||||
long id = DBHelper.insertGroup(mDatabase, groupName);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
assertEquals(groupsToAdd, DBHelper.getGroupCount(mDatabase));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that all of the cards follow the pattern
|
||||
* specified in addLoyaltyCards(), and are in sequential order
|
||||
@@ -285,7 +254,7 @@ public class ImportExportTest {
|
||||
|
||||
/**
|
||||
* Check that all of the groups follow the pattern
|
||||
* specified in addGroups(), and are in sequential order
|
||||
* specified in {@link TestHelpers#addGroups}, and are in sequential order
|
||||
* where the smallest group's index is 1
|
||||
*/
|
||||
private void checkGroups() {
|
||||
@@ -308,7 +277,7 @@ public class ImportExportTest {
|
||||
public void multipleCardsExportImport() throws IOException {
|
||||
final int NUM_CARDS = 10;
|
||||
|
||||
addLoyaltyCards(NUM_CARDS);
|
||||
TestHelpers.addLoyaltyCards(mDatabase, NUM_CARDS);
|
||||
|
||||
ByteArrayOutputStream outData = new ByteArrayOutputStream();
|
||||
OutputStreamWriter outStream = new OutputStreamWriter(outData);
|
||||
@@ -338,7 +307,7 @@ public class ImportExportTest {
|
||||
final int NUM_CARDS = 10;
|
||||
List<char[]> passwords = Arrays.asList(null, "123456789".toCharArray());
|
||||
for (char[] password : passwords) {
|
||||
addLoyaltyCards(NUM_CARDS);
|
||||
TestHelpers.addLoyaltyCards(mDatabase, NUM_CARDS);
|
||||
|
||||
ByteArrayOutputStream outData = new ByteArrayOutputStream();
|
||||
OutputStreamWriter outStream = new OutputStreamWriter(outData);
|
||||
@@ -411,8 +380,8 @@ public class ImportExportTest {
|
||||
final int NUM_CARDS = 10;
|
||||
final int NUM_GROUPS = 3;
|
||||
|
||||
addLoyaltyCards(NUM_CARDS);
|
||||
addGroups(NUM_GROUPS);
|
||||
TestHelpers.addLoyaltyCards(mDatabase, NUM_CARDS);
|
||||
TestHelpers.addGroups(mDatabase, NUM_GROUPS);
|
||||
|
||||
List<Group> emptyGroup = new ArrayList<>();
|
||||
|
||||
@@ -484,7 +453,7 @@ public class ImportExportTest {
|
||||
public void importExistingCardsNotReplace() throws IOException {
|
||||
final int NUM_CARDS = 10;
|
||||
|
||||
addLoyaltyCards(NUM_CARDS);
|
||||
TestHelpers.addLoyaltyCards(mDatabase, NUM_CARDS);
|
||||
|
||||
ByteArrayOutputStream outData = new ByteArrayOutputStream();
|
||||
OutputStreamWriter outStream = new OutputStreamWriter(outData);
|
||||
@@ -513,7 +482,7 @@ public class ImportExportTest {
|
||||
final int NUM_CARDS = 10;
|
||||
|
||||
for (DataFormat format : DataFormat.values()) {
|
||||
addLoyaltyCards(NUM_CARDS);
|
||||
TestHelpers.addLoyaltyCards(mDatabase, NUM_CARDS);
|
||||
|
||||
ByteArrayOutputStream outData = new ByteArrayOutputStream();
|
||||
OutputStreamWriter outStream = new OutputStreamWriter(outData);
|
||||
@@ -558,7 +527,7 @@ public class ImportExportTest {
|
||||
final File sdcardDir = Environment.getExternalStorageDirectory();
|
||||
final File exportFile = new File(sdcardDir, "Catima.csv");
|
||||
|
||||
addLoyaltyCards(NUM_CARDS);
|
||||
TestHelpers.addLoyaltyCards(mDatabase, NUM_CARDS);
|
||||
|
||||
TestTaskCompleteListener listener = new TestTaskCompleteListener();
|
||||
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.app.Activity;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class TestHelpers {
|
||||
static public DBHelper getEmptyDb(Activity activity) {
|
||||
DBHelper db = new DBHelper(activity);
|
||||
private static final String BARCODE_DATA = "428311627547";
|
||||
private static final CatimaBarcode BARCODE_TYPE = CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A);
|
||||
|
||||
public static DBHelper getEmptyDb(Context context) {
|
||||
DBHelper db = new DBHelper(context);
|
||||
SQLiteDatabase database = db.getWritableDatabase();
|
||||
|
||||
// Make sure no files remain
|
||||
@@ -19,7 +28,7 @@ public class TestHelpers {
|
||||
|
||||
for (ImageLocationType imageLocationType : ImageLocationType.values()) {
|
||||
try {
|
||||
Utils.saveCardImage(activity.getApplicationContext(), null, cardID, imageLocationType);
|
||||
Utils.saveCardImage(context.getApplicationContext(), null, cardID, imageLocationType);
|
||||
} catch (FileNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
@@ -34,4 +43,35 @@ public class TestHelpers {
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given number of cards, each with an index in the store name.
|
||||
*
|
||||
* @param mDatabase
|
||||
* @param cardsToAdd
|
||||
*/
|
||||
public static void addLoyaltyCards(final SQLiteDatabase mDatabase, final int cardsToAdd) {
|
||||
// Add in reverse order to test sorting
|
||||
for (int index = cardsToAdd; index > 0; index--) {
|
||||
String storeName = String.format("store, \"%4d", index);
|
||||
String note = String.format("note, \"%4d", index);
|
||||
long id = DBHelper.insertLoyaltyCard(mDatabase, storeName, note, null, null, new BigDecimal(String.valueOf(index)), null, BARCODE_DATA, null, BARCODE_TYPE, index, 0, null,0);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
assertEquals(cardsToAdd, DBHelper.getLoyaltyCardCount(mDatabase));
|
||||
}
|
||||
|
||||
public static void addGroups(final SQLiteDatabase mDatabase, int groupsToAdd) {
|
||||
// Add in reverse order to test sorting
|
||||
for (int index = groupsToAdd; index > 0; index--) {
|
||||
String groupName = String.format("group, \"%4d", index);
|
||||
long id = DBHelper.insertGroup(mDatabase, groupName);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
assertEquals(groupsToAdd, DBHelper.getGroupCount(mDatabase));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
package protect.card_locker.contentprovider;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Currency;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import protect.card_locker.CatimaBarcode;
|
||||
import protect.card_locker.DBHelper;
|
||||
import protect.card_locker.Group;
|
||||
import protect.card_locker.TestHelpers;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class CardsContentProviderTest {
|
||||
private ContentResolver mResolver;
|
||||
private DBHelper dbHelper;
|
||||
private SQLiteDatabase mDatabase;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
final ContentProvider contentProvider = new CardsContentProvider();
|
||||
final ProviderInfo providerInfo = new ProviderInfo();
|
||||
providerInfo.authority = CardsContentProvider.AUTHORITY;
|
||||
contentProvider.attachInfo(RuntimeEnvironment.getApplication(), providerInfo);
|
||||
contentProvider.onCreate();
|
||||
Robolectric.buildContentProvider(CardsContentProvider.class).create(providerInfo);
|
||||
|
||||
mResolver = RuntimeEnvironment.getApplication().getContentResolver();
|
||||
dbHelper = TestHelpers.getEmptyDb(RuntimeEnvironment.getApplication());
|
||||
mDatabase = dbHelper.getWritableDatabase();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
mDatabase.close();
|
||||
dbHelper.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVersion() {
|
||||
final Uri versionUri = getUri("version");
|
||||
|
||||
try (Cursor cursor = mResolver.query(versionUri, null, null, null)) {
|
||||
assertEquals("number of entries", 1, cursor.getCount());
|
||||
assertEquals("number of columns", 2, cursor.getColumnCount());
|
||||
assertArrayEquals("column names", new String[]{"major", "minor"}, cursor.getColumnNames());
|
||||
cursor.moveToNext();
|
||||
assertEquals("major version", 1, cursor.getInt(cursor.getColumnIndexOrThrow("major")));
|
||||
assertEquals("minor version", 0, cursor.getInt(cursor.getColumnIndexOrThrow("minor")));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCards() {
|
||||
final Uri cardsUri = getUri("cards");
|
||||
|
||||
try (Cursor cursor = mResolver.query(cardsUri, null, null, null)) {
|
||||
assertEquals(cursor.getCount(), 0);
|
||||
}
|
||||
|
||||
final String store = "the best store";
|
||||
final String note = "this is a note";
|
||||
final Date validFrom = Date.from(Instant.ofEpochMilli(1687112209000L));
|
||||
final Date expiry = Date.from(Instant.ofEpochMilli(1687112277000L));
|
||||
final BigDecimal balance = new BigDecimal("123.20");
|
||||
final Currency balanceType = Currency.getInstance("EUR");
|
||||
final String cardId = "a-card-id";
|
||||
final String barcodeId = "barcode-id";
|
||||
final CatimaBarcode barcodeType = CatimaBarcode.fromName("QR_CODE");
|
||||
final int headerColor = 0xFFFF00FF;
|
||||
final int starStatus = 1;
|
||||
final long lastUsed = 1687112282000L;
|
||||
final int archiveStatus = 1;
|
||||
long id = DBHelper.insertLoyaltyCard(
|
||||
mDatabase, store, note, validFrom, expiry, balance, balanceType,
|
||||
cardId, barcodeId, barcodeType, headerColor, starStatus, lastUsed,
|
||||
archiveStatus
|
||||
);
|
||||
assertEquals("expect first card", 1, id);
|
||||
|
||||
try (Cursor cursor = mResolver.query(cardsUri, null, null, null)) {
|
||||
assertEquals("number of cards", 1, cursor.getCount());
|
||||
|
||||
final String[] expectedColumns = new String[]{
|
||||
"_id", "store", "validfrom", "expiry", "balance", "balancetype",
|
||||
"note", "headercolor", "cardid", "barcodeid",
|
||||
"barcodetype", "starstatus", "lastused", "archive"
|
||||
};
|
||||
|
||||
assertEquals("number of columns", expectedColumns.length, cursor.getColumnCount());
|
||||
assertEquals(
|
||||
"column names",
|
||||
new HashSet<>(Arrays.asList(expectedColumns)),
|
||||
new HashSet<>(Arrays.asList(cursor.getColumnNames()))
|
||||
);
|
||||
|
||||
cursor.moveToNext();
|
||||
|
||||
final int actualId = cursor.getInt(cursor.getColumnIndexOrThrow("_id"));
|
||||
final String actualName = cursor.getString(cursor.getColumnIndexOrThrow("store"));
|
||||
final String actualNote = cursor.getString(cursor.getColumnIndexOrThrow("note"));
|
||||
final long actualValidFrom = cursor.getLong(cursor.getColumnIndexOrThrow("validfrom"));
|
||||
final long actualExpiry = cursor.getLong(cursor.getColumnIndexOrThrow("expiry"));
|
||||
final BigDecimal actualBalance = new BigDecimal(cursor.getString(cursor.getColumnIndexOrThrow("balance")));
|
||||
final String actualBalanceType = cursor.getString(cursor.getColumnIndexOrThrow("balancetype"));
|
||||
final String actualCardId = cursor.getString(cursor.getColumnIndexOrThrow("cardid"));
|
||||
final String actualBarcodeId = cursor.getString(cursor.getColumnIndexOrThrow("barcodeid"));
|
||||
final String actualBarcodeType = cursor.getString(cursor.getColumnIndexOrThrow("barcodetype"));
|
||||
final int actualHeaderColor = cursor.getInt(cursor.getColumnIndexOrThrow("headercolor"));
|
||||
final int actualStarred = cursor.getInt(cursor.getColumnIndexOrThrow("starstatus"));
|
||||
final long actualLastUsed = cursor.getLong(cursor.getColumnIndexOrThrow("lastused"));
|
||||
final int actualArchiveStatus = cursor.getInt(cursor.getColumnIndexOrThrow("archive"));
|
||||
|
||||
assertEquals("Id", 1, actualId);
|
||||
assertEquals("Name", store, actualName);
|
||||
assertEquals("Note", note, actualNote);
|
||||
assertEquals("ValidFrom", validFrom.getTime(), actualValidFrom);
|
||||
assertEquals("Expiry", expiry.getTime(), actualExpiry);
|
||||
assertEquals("Balance", balance, actualBalance);
|
||||
assertEquals("BalanceTypeColumn", balanceType.toString(), actualBalanceType);
|
||||
assertEquals("CardId", cardId, actualCardId);
|
||||
assertEquals("BarcodeId", barcodeId, actualBarcodeId);
|
||||
assertEquals("BarcodeType", barcodeType.format().name(), actualBarcodeType);
|
||||
assertEquals("HeaderColorColumn", headerColor, actualHeaderColor);
|
||||
assertEquals("Starred", starStatus, actualStarred);
|
||||
assertEquals("LastUsed", lastUsed, actualLastUsed);
|
||||
assertEquals("ArchiveStatus", archiveStatus, actualArchiveStatus);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCardsProjection() {
|
||||
final Uri cardsUri = getUri("cards");
|
||||
|
||||
try (Cursor cursor = mResolver.query(cardsUri, null, null, null)) {
|
||||
assertEquals(cursor.getCount(), 0);
|
||||
}
|
||||
|
||||
TestHelpers.addLoyaltyCards(mDatabase, 1);
|
||||
|
||||
// Query with projection of columns, including internal column names, which should be filtered out
|
||||
try (Cursor cursor = mResolver.query(cardsUri, new String[] {"_id", "store", "zoomlevel"}, null, null)) {
|
||||
assertEquals("number of cards", 1, cursor.getCount());
|
||||
|
||||
assertEquals("number of columns", 2, cursor.getColumnCount());
|
||||
assertArrayEquals("column names", new String[]{"_id", "store"}, cursor.getColumnNames());
|
||||
|
||||
cursor.moveToNext();
|
||||
|
||||
final int actualId = cursor.getInt(cursor.getColumnIndexOrThrow("_id"));
|
||||
final String actualName = cursor.getString(cursor.getColumnIndexOrThrow("store"));
|
||||
|
||||
assertEquals("id", 1, actualId);
|
||||
assertEquals("store", "store, \" 1", actualName);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroups() {
|
||||
final Uri groupsUri = getUri("groups");
|
||||
|
||||
try (Cursor cursor = mResolver.query(groupsUri, null, null, null)) {
|
||||
assertEquals("start without groups", 0, cursor.getCount());
|
||||
}
|
||||
|
||||
TestHelpers.addGroups(mDatabase, 4);
|
||||
|
||||
try (Cursor cursor = mResolver.query(groupsUri, null, null, null)) {
|
||||
assertEquals("number of groups", 4, cursor.getCount());
|
||||
assertEquals("number of columns", 2, cursor.getColumnCount());
|
||||
assertArrayEquals("column names", new String[]{"_id", "orderId"}, cursor.getColumnNames());
|
||||
for (int i = 0; i < 4; i++) {
|
||||
cursor.moveToNext();
|
||||
assertEquals(
|
||||
String.format("groups[%d]._id", i),
|
||||
String.format("group, \"%4d", 4 - i),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow("_id"))
|
||||
);
|
||||
assertEquals(
|
||||
String.format("groups[%d].orderId", i),
|
||||
String.valueOf(i),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow("orderId"))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCardGroups() {
|
||||
final Uri cardGroupsUri = getUri("card_groups");
|
||||
|
||||
try (Cursor cursor = mResolver.query(cardGroupsUri, null, null, null)) {
|
||||
assertEquals(cursor.getCount(), 0);
|
||||
}
|
||||
|
||||
TestHelpers.addLoyaltyCards(mDatabase, 5);
|
||||
TestHelpers.addGroups(mDatabase, 4);
|
||||
|
||||
final List<Group> groupsForOne = new ArrayList<>();
|
||||
groupsForOne.add(DBHelper.getGroup(mDatabase, "group, \" 1"));
|
||||
|
||||
final List<Group> groupsForTwo = new ArrayList<>();
|
||||
groupsForTwo.add(DBHelper.getGroup(mDatabase, "group, \" 1"));
|
||||
groupsForTwo.add(DBHelper.getGroup(mDatabase, "group, \" 2"));
|
||||
|
||||
DBHelper.setLoyaltyCardGroups(mDatabase, 1, groupsForOne);
|
||||
DBHelper.setLoyaltyCardGroups(mDatabase, 2, groupsForTwo);
|
||||
|
||||
final Map<String, List<String>> expectedGroups = new HashMap<>() {{
|
||||
put("group, \" 1", Arrays.asList("1", "2"));
|
||||
put("group, \" 2", Collections.singletonList("2"));
|
||||
}};
|
||||
|
||||
try (Cursor cursor = mResolver.query(cardGroupsUri, null, null, null)) {
|
||||
assertEquals("number of card groups", 3, cursor.getCount());
|
||||
assertEquals("number of columns", 2, cursor.getColumnCount());
|
||||
assertArrayEquals("column names", new String[]{"cardId", "groupId"}, cursor.getColumnNames());
|
||||
|
||||
final Map<String, List<String>> groups = new HashMap<>();
|
||||
while (cursor.moveToNext()) {
|
||||
final String cardId = cursor.getString(cursor.getColumnIndexOrThrow("cardId"));
|
||||
final String groupId = cursor.getString(cursor.getColumnIndexOrThrow("groupId"));
|
||||
groups.computeIfAbsent(groupId, k -> new ArrayList<>()).add(cardId);
|
||||
}
|
||||
assertEquals("expected groups with cards", expectedGroups, groups);
|
||||
}
|
||||
}
|
||||
|
||||
private Uri getUri(final String endpoint) {
|
||||
return Uri.parse(String.format(Locale.ROOT, "content://%s/%s", CardsContentProvider.AUTHORITY, endpoint));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user