package com.code44.finance.data.providers;
import android.content.ContentValues;
import android.database.Cursor;
import com.code44.finance.common.model.ModelState;
import com.code44.finance.common.model.TransactionType;
import com.code44.finance.data.Query;
import com.code44.finance.data.db.Tables;
import com.code44.finance.data.model.Account;
import com.code44.finance.data.model.Transaction;
import com.code44.finance.utils.IOUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import static org.junit.Assert.assertEquals;
@RunWith(RobolectricTestRunner.class)
public class AccountsProviderTest extends BaseContentProviderTestCase {
@Test
public void insert_createsIncomeTransactionToMakeCorrectBalance_whenAccountIsNewAndBalanceIsPositive() {
final Account account = queryAccount(insertAccount(42).getId());
assertEquals(42, account.getBalance());
final Cursor cursor = queryTransactionsCursor();
assertEquals(1, cursor.getCount());
final Transaction transaction = Transaction.from(cursor);
assertEquals(42, transaction.getAmount());
assertEquals(TransactionType.Income, transaction.getCategory().getTransactionType());
IOUtils.closeQuietly(cursor);
}
@Test
public void insert_createsExpenseTransactionToMakeCorrectBalance_whenAccountIsNewAndBalanceIsExpense() {
final Account account = queryAccount(insertAccount(-42).getId());
assertEquals(-42, account.getBalance());
final Cursor cursor = queryTransactionsCursor();
assertEquals(1, cursor.getCount());
final Transaction transaction = Transaction.from(cursor);
assertEquals(42, transaction.getAmount());
assertEquals(TransactionType.Expense, transaction.getCategory().getTransactionType());
IOUtils.closeQuietly(cursor);
}
@Test
public void insert_createsTransactionToMakeCorrectBalance_whenAccountAlreadyExists() {
Account account = queryAccount(insertAccount(0).getId());
assertEquals(0, account.getBalance());
account.setBalance(42);
account = queryAccount(insertAccount(account).getId());
assertEquals(42, account.getBalance());
final Cursor cursor = queryTransactionsCursor();
assertEquals(1, cursor.getCount());
final Transaction transaction = Transaction.from(cursor);
assertEquals(42, transaction.getAmount());
IOUtils.closeQuietly(cursor);
}
@Test
public void insert_doesNotCreateTransaction_whenAccountIsNewAndBalanceIsZero() {
insertAccount(0);
final Cursor cursor = queryTransactionsCursor();
assertEquals(0, cursor.getCount());
IOUtils.closeQuietly(cursor);
}
@Test
public void insert_doesNotCreateTransaction_whenAccountAlreadyExistsAndBalanceIsUnchanged() {
insertAccount(insertAccount(42));
final Cursor cursor = queryTransactionsCursor();
assertEquals(1, cursor.getCount());
IOUtils.closeQuietly(cursor);
}
@Test(expected = IllegalArgumentException.class)
public void update_throwsIllegalArgumentException() {
update(AccountsProvider.uriAccounts(), new ContentValues(), null);
}
@Test
public void deleteDelete_setsItemStateDeletedUndoForTransactions() {
final Account account = insertAccount(0);
insertTransaction(account, null);
insertTransaction(null, account);
deleteAccount(account);
final Cursor cursor = queryTransactionsCursor();
assertEquals(2, cursor.getCount());
assertEquals(ModelState.DeletedUndo, Transaction.from(cursor).getModelState());
cursor.moveToNext();
assertEquals(ModelState.DeletedUndo, Transaction.from(cursor).getModelState());
IOUtils.closeQuietly(cursor);
}
private Account queryAccount(String accountId) {
final Cursor cursor = Query.create()
.projectionLocalId(Tables.Accounts.ID)
.projection(Tables.Accounts.PROJECTION)
.projection(Tables.Currencies.PROJECTION)
.from(Robolectric.getShadowApplication().getApplicationContext(), AccountsProvider.uriAccount(accountId))
.execute();
final Account account = Account.from(cursor);
IOUtils.closeQuietly(cursor);
return account;
}
private Account insertAccount(long balance) {
final Account account = new Account();
account.setTitle("a");
account.setBalance(balance);
return insertAccount(account);
}
private Account insertAccount(Account account) {
insert(AccountsProvider.uriAccounts(), account);
return account;
}
private int deleteAccount(Account account) {
return delete("delete", AccountsProvider.uriAccounts(), Tables.Accounts.ID + "=?", String.valueOf(account.getId()));
}
private Cursor queryTransactionsCursor() {
final Query query = Query.create()
.projectionLocalId(Tables.Transactions.ID)
.projection(Tables.Transactions.PROJECTION)
.projection(Tables.Categories.PROJECTION);
return query(TransactionsProvider.uriTransactions(), query);
}
private Transaction insertTransaction(Account accountFrom, Account accountTo) {
final Transaction transaction = new Transaction();
if (accountFrom != null) {
transaction.setAccountFrom(accountFrom);
}
if (accountTo != null) {
transaction.setAccountTo(accountTo);
}
insert(TransactionsProvider.uriTransactions(), transaction);
return transaction;
}
}