summaryrefslogtreecommitdiff
path: root/rust/actualbudget_queries
diff options
context:
space:
mode:
Diffstat (limited to 'rust/actualbudget_queries')
-rw-r--r--rust/actualbudget_queries/README.md1
-rw-r--r--rust/actualbudget_queries/tests/actualbudget_accounts.rs10
-rw-r--r--rust/actualbudget_queries/tests/actualbudget_categories.rs14
-rw-r--r--rust/actualbudget_queries/tests/actualbudget_transactions.rs10
-rw-r--r--rust/actualbudget_queries/tests/actualbudget_zero_budgets.rs2
-rw-r--r--rust/actualbudget_queries/tests/common/account_names.rs17
-rw-r--r--rust/actualbudget_queries/tests/common/category_names.rs29
-rw-r--r--rust/actualbudget_queries/tests/common/db_url.rs (renamed from rust/actualbudget_queries/tests/common.rs)0
-rw-r--r--rust/actualbudget_queries/tests/common/get_reference_data.rs45
-rw-r--r--rust/actualbudget_queries/tests/common/mod.rs5
-rw-r--r--rust/actualbudget_queries/tests/common/transaction_matchers.rs314
-rw-r--r--rust/actualbudget_queries/tests/resources/actualbudget_test_db.sqlitebin528384 -> 528384 bytes
-rw-r--r--rust/actualbudget_queries/tests/resources/actualbudget_test_db_metadata.json2
13 files changed, 430 insertions, 19 deletions
diff --git a/rust/actualbudget_queries/README.md b/rust/actualbudget_queries/README.md
index d16fa30..69ab0e7 100644
--- a/rust/actualbudget_queries/README.md
+++ b/rust/actualbudget_queries/README.md
@@ -34,7 +34,6 @@ To re-create the test database from scratch:
'Food', for 8 Aug, Sept, Oct, and Nov 2024
11. In the 'Category transfers' account, add a transaction for 23rd Oct 2024,
transferring 120.00 from 'Savings' to 'General'
-12.
12. Export the database by going to Settings > Export data
13. Download the resulting ZIP archive
14. Extract `db.sqlite` and `metadata.json`
diff --git a/rust/actualbudget_queries/tests/actualbudget_accounts.rs b/rust/actualbudget_queries/tests/actualbudget_accounts.rs
index a761c4f..fce5dfb 100644
--- a/rust/actualbudget_queries/tests/actualbudget_accounts.rs
+++ b/rust/actualbudget_queries/tests/actualbudget_accounts.rs
@@ -1,7 +1,7 @@
mod common;
use actualbudget_queries::actualbudget_accounts::{get_all_actualbudget_accounts, get_category_transfers_account};
-use common::DB_URL;
+use common::{account_names::ACCOUNT_NAMES, db_url::DB_URL};
use diesel::{Connection, SqliteConnection};
#[test]
@@ -12,10 +12,10 @@ fn given_test_database_when_get_all_accounts_then_return_accounts() {
assert!(accounts.is_ok());
let accounts = accounts.unwrap();
- assert_eq!(3, accounts.len());
- assert!(accounts.iter().any(|a| a.name == "My bank account"));
- assert!(accounts.iter().any(|a| a.name == "My cash account"));
- assert!(accounts.iter().any(|a| a.name == "Category transfers"));
+ assert_eq!(ACCOUNT_NAMES.len(), accounts.len());
+ for account_name in ACCOUNT_NAMES {
+ assert!(accounts.iter().any(|a| a.name.as_str() == *account_name));
+ }
}
#[test]
diff --git a/rust/actualbudget_queries/tests/actualbudget_categories.rs b/rust/actualbudget_queries/tests/actualbudget_categories.rs
index 5cc619f..1e0682c 100644
--- a/rust/actualbudget_queries/tests/actualbudget_categories.rs
+++ b/rust/actualbudget_queries/tests/actualbudget_categories.rs
@@ -1,7 +1,7 @@
mod common;
use actualbudget_queries::actualbudget_categories::get_all_actualbudget_categories;
-use common::DB_URL;
+use common::{category_names::CATEGORY_NAMES, db_url::DB_URL};
use diesel::{Connection, SqliteConnection};
#[test]
@@ -12,12 +12,8 @@ fn given_test_database_when_get_all_categories_then_return_categories() {
assert!(categories.is_ok());
let categories = categories.unwrap();
- assert_eq!(7, categories.len());
- assert!(categories.iter().any(|a| a.name == "Food"));
- assert!(categories.iter().any(|a| a.name == "General"));
- assert!(categories.iter().any(|a| a.name == "Bills"));
- assert!(categories.iter().any(|a| a.name == "Bills (Flexible)"));
- assert!(categories.iter().any(|a| a.name == "Savings"));
- assert!(categories.iter().any(|a| a.name == "Starting Balances"));
- assert!(categories.iter().any(|a| a.name == "Income"));
+ assert_eq!(CATEGORY_NAMES.len(), categories.len());
+ for &category_name in CATEGORY_NAMES {
+ assert!(categories.iter().any(|a| a.name.as_str() == category_name));
+ }
}
diff --git a/rust/actualbudget_queries/tests/actualbudget_transactions.rs b/rust/actualbudget_queries/tests/actualbudget_transactions.rs
index 0321d73..b42d021 100644
--- a/rust/actualbudget_queries/tests/actualbudget_transactions.rs
+++ b/rust/actualbudget_queries/tests/actualbudget_transactions.rs
@@ -1,18 +1,24 @@
mod common;
use actualbudget_queries::actualbudget_transactions::{get_all_actualbudget_transactions, get_first_actualbudget_transaction_date};
-use common::DB_URL;
+use common::{db_url::DB_URL, get_reference_data::{get_accounts, get_categories}, transaction_matchers::get_transaction_matchers};
use diesel::{Connection, SqliteConnection};
#[test]
fn given_test_database_when_get_all_transactions_then_return_transactions() {
let connection = &mut SqliteConnection::establish(DB_URL).unwrap();
+ let accounts = get_accounts(connection);
+ let categories = get_categories(connection);
let transactions = get_all_actualbudget_transactions(connection);
assert!(transactions.is_ok());
let transactions = transactions.unwrap();
- assert_eq!(15, transactions.len());
+ let transaction_matchers = get_transaction_matchers();
+ assert_eq!(transaction_matchers.len(), transactions.len());
+ for transaction_matcher in transaction_matchers {
+ assert!(transactions.iter().any(|t| transaction_matcher(t, &accounts, &categories)));
+ }
}
#[test]
diff --git a/rust/actualbudget_queries/tests/actualbudget_zero_budgets.rs b/rust/actualbudget_queries/tests/actualbudget_zero_budgets.rs
index c4e79be..4e9ea19 100644
--- a/rust/actualbudget_queries/tests/actualbudget_zero_budgets.rs
+++ b/rust/actualbudget_queries/tests/actualbudget_zero_budgets.rs
@@ -1,7 +1,7 @@
mod common;
use actualbudget_queries::actualbudget_zero_budgets::get_all_actualbudget_zero_budgets;
-use common::DB_URL;
+use common::db_url::DB_URL;
use diesel::{Connection, SqliteConnection};
#[test]
diff --git a/rust/actualbudget_queries/tests/common/account_names.rs b/rust/actualbudget_queries/tests/common/account_names.rs
new file mode 100644
index 0000000..1abee4b
--- /dev/null
+++ b/rust/actualbudget_queries/tests/common/account_names.rs
@@ -0,0 +1,17 @@
+pub const ACCOUNT_NAMES: &[&'static str] = &[
+ "My bank account",
+ "My cash account",
+ "Category transfers",
+];
+
+pub struct AccountNamesDict {
+ pub bank_account: &'static str,
+ pub cash_account: &'static str,
+ pub transfers_account: &'static str,
+}
+
+pub const ACCOUNT_NAMES_DICT: AccountNamesDict = AccountNamesDict {
+ bank_account: ACCOUNT_NAMES[0],
+ cash_account: ACCOUNT_NAMES[1],
+ transfers_account: ACCOUNT_NAMES[2],
+};
diff --git a/rust/actualbudget_queries/tests/common/category_names.rs b/rust/actualbudget_queries/tests/common/category_names.rs
new file mode 100644
index 0000000..a2f7d84
--- /dev/null
+++ b/rust/actualbudget_queries/tests/common/category_names.rs
@@ -0,0 +1,29 @@
+pub const CATEGORY_NAMES: &[&'static str] = &[
+ "Food",
+ "General",
+ "Bills",
+ "Bills (Flexible)",
+ "Savings",
+ "Starting Balances",
+ "Income",
+];
+
+pub struct CategoryNamesDict {
+ pub food: &'static str,
+ pub general: &'static str,
+ pub bills: &'static str,
+ pub bills_flexible: &'static str,
+ pub savings: &'static str,
+ pub starting_balances: &'static str,
+ pub income: &'static str,
+}
+
+pub const CATEGORY_NAMES_DICT: CategoryNamesDict = CategoryNamesDict {
+ food: CATEGORY_NAMES[0],
+ general: CATEGORY_NAMES[1],
+ bills: CATEGORY_NAMES[2],
+ bills_flexible: CATEGORY_NAMES[3],
+ savings: CATEGORY_NAMES[4],
+ starting_balances: CATEGORY_NAMES[5],
+ income: CATEGORY_NAMES[6],
+};
diff --git a/rust/actualbudget_queries/tests/common.rs b/rust/actualbudget_queries/tests/common/db_url.rs
index ff778a8..ff778a8 100644
--- a/rust/actualbudget_queries/tests/common.rs
+++ b/rust/actualbudget_queries/tests/common/db_url.rs
diff --git a/rust/actualbudget_queries/tests/common/get_reference_data.rs b/rust/actualbudget_queries/tests/common/get_reference_data.rs
new file mode 100644
index 0000000..d317a00
--- /dev/null
+++ b/rust/actualbudget_queries/tests/common/get_reference_data.rs
@@ -0,0 +1,45 @@
+use std::collections::HashMap;
+
+use actualbudget_models::{actualbudget_account::ActualbudgetAccount, actualbudget_category::ActualbudgetCategory};
+use actualbudget_queries::{actualbudget_accounts::get_all_actualbudget_accounts, actualbudget_categories::get_all_actualbudget_categories, actualbudget_transactions::{get_all_actualbudget_transactions, get_first_actualbudget_transaction_date}};
+use diesel::SqliteConnection;
+
+use super::{account_names::ACCOUNT_NAMES, category_names::CATEGORY_NAMES};
+
+pub fn get_accounts(connection: &mut SqliteConnection) -> HashMap<String, ActualbudgetAccount> {
+ let accounts = get_all_actualbudget_accounts(connection).expect("failed to get accounts");
+ let mut accounts_hash_map = HashMap::new();
+
+ for &account_name in ACCOUNT_NAMES {
+ let account = accounts
+ .clone()
+ .into_iter()
+ .find(|a| a.name.as_str() == account_name)
+ .expect(&format!("failed to get account: {}", account_name));
+ accounts_hash_map.insert(
+ String::from(account_name),
+ account,
+ );
+ }
+
+ accounts_hash_map
+}
+
+pub fn get_categories(connection: &mut SqliteConnection) -> HashMap<String, ActualbudgetCategory> {
+ let categories = get_all_actualbudget_categories(connection).expect("failed to get categories");
+ let mut categories_hash_map = HashMap::new();
+
+ for &category_name in CATEGORY_NAMES {
+ let category = categories
+ .clone()
+ .into_iter()
+ .find(|a| a.name.as_str() == category_name)
+ .expect(&format!("failed to get category: {}", category_name));
+ categories_hash_map.insert(
+ String::from(category_name),
+ category,
+ );
+ }
+
+ categories_hash_map
+}
diff --git a/rust/actualbudget_queries/tests/common/mod.rs b/rust/actualbudget_queries/tests/common/mod.rs
new file mode 100644
index 0000000..01112b3
--- /dev/null
+++ b/rust/actualbudget_queries/tests/common/mod.rs
@@ -0,0 +1,5 @@
+pub mod account_names;
+pub mod category_names;
+pub mod db_url;
+pub mod get_reference_data;
+pub mod transaction_matchers;
diff --git a/rust/actualbudget_queries/tests/common/transaction_matchers.rs b/rust/actualbudget_queries/tests/common/transaction_matchers.rs
new file mode 100644
index 0000000..f245723
--- /dev/null
+++ b/rust/actualbudget_queries/tests/common/transaction_matchers.rs
@@ -0,0 +1,314 @@
+use std::collections::HashMap;
+
+use actualbudget_models::{actualbudget_account::ActualbudgetAccount, actualbudget_category::ActualbudgetCategory, actualbudget_transaction::ActualbudgetTransaction};
+
+use super::{account_names::ACCOUNT_NAMES_DICT, category_names::CATEGORY_NAMES_DICT};
+
+pub fn get_transaction_matchers() -> Vec<Box<dyn Fn(&ActualbudgetTransaction, &HashMap<String, ActualbudgetAccount>, &HashMap<String, ActualbudgetCategory>) -> bool>> {
+ vec![
+ Box::new(|t, a, c| matches_bank_account_initial_transaction(t, a, c)),
+ Box::new(|t, a, c| matches_cash_account_initial_transaction(t, a, c)),
+ Box::new(|t, a, c| matches_income_transaction(t, a, c, "08")),
+ Box::new(|t, a, c| matches_income_transaction(t, a, c, "09")),
+ Box::new(|t, a, c| matches_income_transaction(t, a, c, "10")),
+ Box::new(|t, a, c| matches_income_transaction(t, a, c, "11")),
+ Box::new(|t, a, c| matches_food_transaction(t, a, c, "08")),
+ Box::new(|t, a, c| matches_food_transaction(t, a, c, "09")),
+ Box::new(|t, a, c| matches_food_transaction(t, a, c, "10")),
+ Box::new(|t, a, c| matches_food_transaction(t, a, c, "11")),
+ Box::new(|t, a, c| matches_category_transfer_parent_transaction(t, a, c)),
+ Box::new(|t, a, c| matches_category_transfer_child_out_transaction(t, a, c)),
+ Box::new(|t, a, c| matches_category_transfer_child_in_transaction(t, a, c)),
+ Box::new(|t, a, c| matches_account_transfer_out_transaction(t, a, c)),
+ Box::new(|t, a, c| matches_account_transfer_in_transaction(t, a, c)),
+ ]
+}
+
+fn matches_bank_account_initial_transaction(
+ t: &ActualbudgetTransaction,
+ accounts: &HashMap<String, ActualbudgetAccount>,
+ categories: &HashMap<String, ActualbudgetCategory>,
+) -> bool {
+ let bank_account_id = accounts
+ .get(ACCOUNT_NAMES_DICT.bank_account)
+ .expect("failed to find bank account")
+ .id
+ .clone();
+
+ let starting_balances_category_id = categories
+ .get(CATEGORY_NAMES_DICT.starting_balances)
+ .expect("failed to find starting balances category")
+ .id
+ .clone();
+
+ match t {
+ ActualbudgetTransaction {
+ is_parent: false,
+ is_child: false,
+ parent_id: None,
+ account_id,
+ category_id: Some(category_id),
+ amount: 1200_00,
+ date,
+ ..
+ } => *account_id == bank_account_id
+ && *category_id == starting_balances_category_id
+ && date.to_iso() == "2024-08-01",
+ _ => false,
+ }
+}
+
+fn matches_cash_account_initial_transaction(
+ t: &ActualbudgetTransaction,
+ accounts: &HashMap<String, ActualbudgetAccount>,
+ categories: &HashMap<String, ActualbudgetCategory>,
+) -> bool {
+ let bank_account_id = accounts
+ .get(ACCOUNT_NAMES_DICT.cash_account)
+ .expect("failed to find cash account")
+ .id
+ .clone();
+
+ let starting_balances_category_id = categories
+ .get(CATEGORY_NAMES_DICT.starting_balances)
+ .expect("failed to find starting balances category")
+ .id
+ .clone();
+
+ match t {
+ ActualbudgetTransaction {
+ is_parent: false,
+ is_child: false,
+ parent_id: None,
+ account_id,
+ category_id: Some(category_id),
+ amount: 45_10,
+ date,
+ ..
+ } => *account_id == bank_account_id
+ && *category_id == starting_balances_category_id
+ && date.to_iso() == "2024-08-01",
+ _ => false,
+ }
+}
+
+fn matches_income_transaction(
+ t: &ActualbudgetTransaction,
+ accounts: &HashMap<String, ActualbudgetAccount>,
+ categories: &HashMap<String, ActualbudgetCategory>,
+ month: &str,
+) -> bool {
+ let bank_account_id = accounts
+ .get(ACCOUNT_NAMES_DICT.bank_account)
+ .expect("failed to find bank account")
+ .id
+ .clone();
+
+ let income_category_id = categories
+ .get(CATEGORY_NAMES_DICT.income)
+ .expect("failed to find income category")
+ .id
+ .clone();
+
+ match t {
+ ActualbudgetTransaction {
+ is_parent: false,
+ is_child: false,
+ parent_id: None,
+ account_id,
+ category_id,
+ amount: 846_46,
+ date,
+ notes: Some(notes),
+ ..
+ } => *account_id == bank_account_id
+ && *category_id == Some(income_category_id)
+ && date.to_iso() == format!("2024-{}-21", month)
+ && *notes == String::from("Salary"),
+ _ => false,
+ }
+}
+
+fn matches_food_transaction(
+ t: &ActualbudgetTransaction,
+ accounts: &HashMap<String, ActualbudgetAccount>,
+ categories: &HashMap<String, ActualbudgetCategory>,
+ month: &str,
+) -> bool {
+ let bank_account_id = accounts
+ .get(ACCOUNT_NAMES_DICT.bank_account)
+ .expect("failed to find bank account")
+ .id
+ .clone();
+
+ let income_category_id = categories
+ .get(CATEGORY_NAMES_DICT.food)
+ .expect("failed to find food category")
+ .id
+ .clone();
+
+ match t {
+ ActualbudgetTransaction {
+ is_parent: false,
+ is_child: false,
+ parent_id: None,
+ account_id,
+ category_id,
+ amount: -200_00,
+ date,
+ ..
+ } => *account_id == bank_account_id
+ && *category_id == Some(income_category_id)
+ && date.to_iso() == format!("2024-{}-08", month),
+ _ => false,
+ }
+}
+
+fn matches_category_transfer_parent_transaction(
+ t: &ActualbudgetTransaction,
+ accounts: &HashMap<String, ActualbudgetAccount>,
+ _categories: &HashMap<String, ActualbudgetCategory>,
+) -> bool {
+ let category_transfers_account_id = accounts
+ .get(ACCOUNT_NAMES_DICT.transfers_account)
+ .expect("failed to find transfers account")
+ .id
+ .clone();
+
+ match t {
+ ActualbudgetTransaction {
+ is_parent: true,
+ is_child: false,
+ parent_id: None,
+ account_id,
+ category_id: None,
+ amount: 0,
+ date,
+ ..
+ } => *account_id == category_transfers_account_id
+ && date.to_iso() == "2024-10-23",
+ _ => false,
+ }
+}
+
+fn matches_category_transfer_child_out_transaction(
+ t: &ActualbudgetTransaction,
+ accounts: &HashMap<String, ActualbudgetAccount>,
+ categories: &HashMap<String, ActualbudgetCategory>,
+) -> bool {
+ let category_transfers_account_id = accounts
+ .get(ACCOUNT_NAMES_DICT.transfers_account)
+ .expect("failed to find transfers account")
+ .id
+ .clone();
+
+ let savings_category_id = categories
+ .get(CATEGORY_NAMES_DICT.savings)
+ .expect("failed to find savings category")
+ .id
+ .clone();
+
+ match t {
+ ActualbudgetTransaction {
+ is_parent: false,
+ is_child: true,
+ parent_id: Some(_),
+ account_id,
+ category_id: Some(category_id),
+ amount: -120_00,
+ date,
+ ..
+ } => *account_id == category_transfers_account_id
+ && *category_id == savings_category_id
+ && date.to_iso() == "2024-10-23",
+ _ => false,
+ }
+}
+
+fn matches_category_transfer_child_in_transaction(
+ t: &ActualbudgetTransaction,
+ accounts: &HashMap<String, ActualbudgetAccount>,
+ categories: &HashMap<String, ActualbudgetCategory>,
+) -> bool {
+ let category_transfers_account_id = accounts
+ .get(ACCOUNT_NAMES_DICT.transfers_account)
+ .expect("failed to find transfers account")
+ .id
+ .clone();
+
+ let savings_category_id = categories
+ .get(CATEGORY_NAMES_DICT.general)
+ .expect("failed to find general category")
+ .id
+ .clone();
+
+ match t {
+ ActualbudgetTransaction {
+ is_parent: false,
+ is_child: true,
+ parent_id: Some(_),
+ account_id,
+ category_id: Some(category_id),
+ amount: 120_00,
+ date,
+ ..
+ } => *account_id == category_transfers_account_id
+ && *category_id == savings_category_id
+ && date.to_iso() == "2024-10-23",
+ _ => false,
+ }
+}
+
+fn matches_account_transfer_out_transaction(
+ t: &ActualbudgetTransaction,
+ accounts: &HashMap<String, ActualbudgetAccount>,
+ categories: &HashMap<String, ActualbudgetCategory>,
+) -> bool {
+ let bank_account_id = accounts
+ .get(ACCOUNT_NAMES_DICT.bank_account)
+ .expect("failed to find bank account")
+ .id
+ .clone();
+
+ match t {
+ ActualbudgetTransaction {
+ is_parent: false,
+ is_child: false,
+ parent_id: None,
+ account_id,
+ category_id: None,
+ amount: -80_00,
+ date,
+ ..
+ } => *account_id == bank_account_id
+ && date.to_iso() == "2024-09-10",
+ _ => false,
+ }
+}
+
+fn matches_account_transfer_in_transaction(
+ t: &ActualbudgetTransaction,
+ accounts: &HashMap<String, ActualbudgetAccount>,
+ categories: &HashMap<String, ActualbudgetCategory>,
+) -> bool {
+ let cash_account_id = accounts
+ .get(ACCOUNT_NAMES_DICT.cash_account)
+ .expect("failed to find cash account")
+ .id
+ .clone();
+
+ match t {
+ ActualbudgetTransaction {
+ is_parent: false,
+ is_child: false,
+ parent_id: None,
+ account_id,
+ category_id: None,
+ amount: 80_00,
+ date,
+ ..
+ } => *account_id == cash_account_id
+ && date.to_iso() == "2024-09-10",
+ _ => false,
+ }
+}
diff --git a/rust/actualbudget_queries/tests/resources/actualbudget_test_db.sqlite b/rust/actualbudget_queries/tests/resources/actualbudget_test_db.sqlite
index e22762f..4146bb0 100644
--- a/rust/actualbudget_queries/tests/resources/actualbudget_test_db.sqlite
+++ b/rust/actualbudget_queries/tests/resources/actualbudget_test_db.sqlite
Binary files differ
diff --git a/rust/actualbudget_queries/tests/resources/actualbudget_test_db_metadata.json b/rust/actualbudget_queries/tests/resources/actualbudget_test_db_metadata.json
index c323ad6..4d83f81 100644
--- a/rust/actualbudget_queries/tests/resources/actualbudget_test_db_metadata.json
+++ b/rust/actualbudget_queries/tests/resources/actualbudget_test_db_metadata.json
@@ -1 +1 @@
-{"id":"My-Finances-1-36ec11a","budgetName":"My Finances 1","userId":"fec9ba17-c260-4f55-8d44-676ef0ec5da9","lastScheduleRun":"2024-11-17","resetClock":true} \ No newline at end of file
+{"id":"My-Finances-1-36ec11a","budgetName":"My Finances 1","userId":"fec9ba17-c260-4f55-8d44-676ef0ec5da9","lastScheduleRun":"2024-11-21","resetClock":true} \ No newline at end of file