From a82fdd49468f1020fbdb3b2dfef8770cf65efc3d Mon Sep 17 00:00:00 2001 From: MaysWind Date: Sat, 20 Sep 2025 21:08:42 +0800 Subject: [PATCH] add unit tests --- pkg/services/accounts_test.go | 218 ++++++++++++++ pkg/services/transaction_categories_test.go | 301 ++++++++++++++++++++ 2 files changed, 519 insertions(+) create mode 100644 pkg/services/accounts_test.go create mode 100644 pkg/services/transaction_categories_test.go diff --git a/pkg/services/accounts_test.go b/pkg/services/accounts_test.go new file mode 100644 index 00000000..173fe3fb --- /dev/null +++ b/pkg/services/accounts_test.go @@ -0,0 +1,218 @@ +package services + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/mayswind/ezbookkeeping/pkg/models" +) + +func TestGetAccountMapByList_EmptyList(t *testing.T) { + accounts := make([]*models.Account, 0) + actualAccountMap := Accounts.GetAccountMapByList(accounts) + + assert.NotNil(t, actualAccountMap) + assert.Equal(t, 0, len(actualAccountMap)) +} + +func TestGetAccountMapByList_MultipleList(t *testing.T) { + accounts := []*models.Account{ + { + AccountId: 1001, + Name: "Cash Account", + Category: models.ACCOUNT_CATEGORY_CASH, + }, + { + AccountId: 1002, + Name: "Checking Account", + Category: models.ACCOUNT_CATEGORY_CHECKING_ACCOUNT, + }, + { + AccountId: 1003, + Name: "Credit Card", + Category: models.ACCOUNT_CATEGORY_CREDIT_CARD, + }, + } + actualAccountMap := Accounts.GetAccountMapByList(accounts) + + assert.Equal(t, 3, len(actualAccountMap)) + assert.Contains(t, actualAccountMap, int64(1001)) + assert.Contains(t, actualAccountMap, int64(1002)) + assert.Contains(t, actualAccountMap, int64(1003)) + assert.Equal(t, "Cash Account", actualAccountMap[1001].Name) + assert.Equal(t, "Checking Account", actualAccountMap[1002].Name) + assert.Equal(t, "Credit Card", actualAccountMap[1003].Name) +} + +func TestGetVisibleAccountNameMapByList_EmptyList(t *testing.T) { + accounts := make([]*models.Account, 0) + actualAccountMap := Accounts.GetVisibleAccountNameMapByList(accounts) + + assert.NotNil(t, actualAccountMap) + assert.Equal(t, 0, len(actualAccountMap)) +} + +func TestGetVisibleAccountNameMapByList_WithHiddenAccount(t *testing.T) { + accounts := []*models.Account{ + { + AccountId: 1001, + Name: "Visible Account", + Type: models.ACCOUNT_TYPE_SINGLE_ACCOUNT, + Hidden: false, + }, + { + AccountId: 1002, + Name: "Hidden Account", + Type: models.ACCOUNT_TYPE_SINGLE_ACCOUNT, + Hidden: true, + }, + } + actualAccountMap := Accounts.GetVisibleAccountNameMapByList(accounts) + + assert.Equal(t, 1, len(actualAccountMap)) + assert.Contains(t, actualAccountMap, "Visible Account") + assert.NotContains(t, actualAccountMap, "Hidden Account") +} + +func TestGetVisibleAccountNameMapByList_WithParentAccount(t *testing.T) { + accounts := []*models.Account{ + { + AccountId: 1001, + Name: "Single Account", + Type: models.ACCOUNT_TYPE_SINGLE_ACCOUNT, + Hidden: false, + }, + { + AccountId: 1002, + Name: "Multi Sub Accounts", + Type: models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS, + Hidden: false, + }, + } + actualAccountMap := Accounts.GetVisibleAccountNameMapByList(accounts) + assert.Equal(t, 1, len(actualAccountMap)) + assert.Contains(t, actualAccountMap, "Single Account") + assert.NotContains(t, actualAccountMap, "Multi Sub Accounts") +} + +func TestGetAccountNames_EmptyList(t *testing.T) { + accounts := make([]*models.Account, 0) + actualAccountMap := Accounts.GetAccountNames(accounts) + + assert.NotNil(t, actualAccountMap) + assert.Equal(t, 0, len(actualAccountMap)) +} + +func TestGetAccountNames_MultipleList(t *testing.T) { + accounts := []*models.Account{ + { + AccountId: 1001, + Name: "Cash Account", + }, + { + AccountId: 1002, + Name: "Checking Account", + }, + { + AccountId: 1003, + Name: "Credit Card", + }, + } + actualAccountMap := Accounts.GetAccountNames(accounts) + + assert.Equal(t, 3, len(actualAccountMap)) + assert.Equal(t, "Cash Account", actualAccountMap[0]) + assert.Equal(t, "Checking Account", actualAccountMap[1]) + assert.Equal(t, "Credit Card", actualAccountMap[2]) +} + +func TestGetAccountOrSubAccountIdsByAccountName_EmptyList(t *testing.T) { + accounts := make([]*models.Account, 0) + actualAccountMap := Accounts.GetAccountOrSubAccountIdsByAccountName(accounts, "Test Account") + + assert.NotNil(t, actualAccountMap) + assert.Equal(t, 0, len(actualAccountMap)) +} + +func TestGetAccountOrSubAccountIdsByAccountName_NotMatch(t *testing.T) { + accounts := []*models.Account{ + { + AccountId: 1001, + Name: "Cash Account", + Type: models.ACCOUNT_TYPE_SINGLE_ACCOUNT, + }, + } + actualAccountMap := Accounts.GetAccountOrSubAccountIdsByAccountName(accounts, "Non-existent Account") + + assert.NotNil(t, actualAccountMap) + assert.Equal(t, 0, len(actualAccountMap)) +} + +func TestGetAccountOrSubAccountIdsByAccountName_MatchSingle(t *testing.T) { + accounts := []*models.Account{ + { + AccountId: 1001, + Name: "Cash Account", + Type: models.ACCOUNT_TYPE_SINGLE_ACCOUNT, + }, + } + actualAccountMap := Accounts.GetAccountOrSubAccountIdsByAccountName(accounts, "Cash Account") + assert.Equal(t, 1, len(actualAccountMap)) + assert.Contains(t, actualAccountMap, int64(1001)) +} + +func TestGetAccountOrSubAccountIdsByAccountName_MatchMultiple(t *testing.T) { + accounts := []*models.Account{ + { + AccountId: 1001, + Name: "Test Account", + Type: models.ACCOUNT_TYPE_SINGLE_ACCOUNT, + }, + { + AccountId: 2001, + Name: "Test Account", + Type: models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS, + ParentAccountId: 0, + }, + { + AccountId: 2002, + Name: "Sub 1-1", + Type: models.ACCOUNT_TYPE_SINGLE_ACCOUNT, + ParentAccountId: 2001, + }, + { + AccountId: 2003, + Name: "Sub 1-2", + Type: models.ACCOUNT_TYPE_SINGLE_ACCOUNT, + ParentAccountId: 2001, + }, + { + AccountId: 3001, + Name: "Test Account", + Type: models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS, + ParentAccountId: 0, + }, + { + AccountId: 3002, + Name: "Sub 2-1", + Type: models.ACCOUNT_TYPE_SINGLE_ACCOUNT, + ParentAccountId: 3001, + }, + { + AccountId: 4001, + Name: "Other Account", + Type: models.ACCOUNT_TYPE_SINGLE_ACCOUNT, + }, + } + actualAccountMap := Accounts.GetAccountOrSubAccountIdsByAccountName(accounts, "Test Account") + + assert.Equal(t, 4, len(actualAccountMap)) + assert.Contains(t, actualAccountMap, int64(1001)) + assert.Contains(t, actualAccountMap, int64(2002)) + assert.Contains(t, actualAccountMap, int64(2003)) + assert.Contains(t, actualAccountMap, int64(3002)) + assert.NotContains(t, actualAccountMap, int64(2001)) + assert.NotContains(t, actualAccountMap, int64(3001)) + assert.NotContains(t, actualAccountMap, int64(4001)) +} diff --git a/pkg/services/transaction_categories_test.go b/pkg/services/transaction_categories_test.go new file mode 100644 index 00000000..706f8c0d --- /dev/null +++ b/pkg/services/transaction_categories_test.go @@ -0,0 +1,301 @@ +package services + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/mayswind/ezbookkeeping/pkg/models" +) + +func TestGetCategoryMapByList_EmptyList(t *testing.T) { + categories := make([]*models.TransactionCategory, 0) + actualCategoryMap := TransactionCategories.GetCategoryMapByList(categories) + + assert.NotNil(t, actualCategoryMap) + assert.Equal(t, 0, len(actualCategoryMap)) +} + +func TestGetCategoryMapByList_MultipleCategories(t *testing.T) { + categories := []*models.TransactionCategory{ + { + CategoryId: 1001, + Name: "Category Name", + Type: models.CATEGORY_TYPE_EXPENSE, + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + Hidden: false, + }, + { + CategoryId: 1002, + Name: "Category Name2", + Type: models.CATEGORY_TYPE_INCOME, + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + Hidden: false, + }, + { + CategoryId: 1003, + Name: "Category Name3", + Type: models.CATEGORY_TYPE_TRANSFER, + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + Hidden: true, + }, + } + actualCategoryMap := TransactionCategories.GetCategoryMapByList(categories) + + assert.Equal(t, 3, len(actualCategoryMap)) + assert.Contains(t, actualCategoryMap, int64(1001)) + assert.Contains(t, actualCategoryMap, int64(1002)) + assert.Contains(t, actualCategoryMap, int64(1003)) + assert.Equal(t, "Category Name", actualCategoryMap[1001].Name) + assert.Equal(t, "Category Name2", actualCategoryMap[1002].Name) + assert.Equal(t, "Category Name3", actualCategoryMap[1003].Name) +} + +func TestGetVisibleSubCategoryNameMapByList_EmptyList(t *testing.T) { + categories := make([]*models.TransactionCategory, 0) + expenseCategoryMap, incomeCategoryMap, transferCategoryMap := TransactionCategories.GetVisibleSubCategoryNameMapByList(categories) + + assert.NotNil(t, expenseCategoryMap) + assert.NotNil(t, incomeCategoryMap) + assert.NotNil(t, transferCategoryMap) + assert.Equal(t, 0, len(expenseCategoryMap)) + assert.Equal(t, 0, len(incomeCategoryMap)) + assert.Equal(t, 0, len(transferCategoryMap)) +} + +func TestGetVisibleSubCategoryNameMapByList_OnlyParentCategories(t *testing.T) { + categories := []*models.TransactionCategory{ + { + CategoryId: 1001, + Name: "Category Name", + Type: models.CATEGORY_TYPE_EXPENSE, + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + Hidden: false, + }, + { + CategoryId: 1002, + Name: "Category Name2", + Type: models.CATEGORY_TYPE_INCOME, + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + Hidden: false, + }, + } + expenseCategoryMap, incomeCategoryMap, transferCategoryMap := TransactionCategories.GetVisibleSubCategoryNameMapByList(categories) + + assert.Equal(t, 0, len(expenseCategoryMap)) + assert.Equal(t, 0, len(incomeCategoryMap)) + assert.Equal(t, 0, len(transferCategoryMap)) +} + +func TestGetVisibleSubCategoryNameMapByList_WithHiddenCategories(t *testing.T) { + categories := []*models.TransactionCategory{ + { + CategoryId: 1001, + Name: "Category Name", + Type: models.CATEGORY_TYPE_EXPENSE, + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + Hidden: false, + }, + { + CategoryId: 2001, + Name: "Category Name2", + Type: models.CATEGORY_TYPE_EXPENSE, + ParentCategoryId: 1001, + Hidden: true, + }, + { + CategoryId: 2002, + Name: "Category Name3", + Type: models.CATEGORY_TYPE_EXPENSE, + ParentCategoryId: 1001, + Hidden: false, + }, + } + expenseCategoryMap, incomeCategoryMap, transferCategoryMap := TransactionCategories.GetVisibleSubCategoryNameMapByList(categories) + + assert.Equal(t, 1, len(expenseCategoryMap)) + assert.Contains(t, expenseCategoryMap, "Category Name3") + assert.NotContains(t, expenseCategoryMap, "Category Name2") + assert.Equal(t, 0, len(incomeCategoryMap)) + assert.Equal(t, 0, len(transferCategoryMap)) +} + +func TestGetVisibleSubCategoryNameMapByList_AllTypes(t *testing.T) { + categories := []*models.TransactionCategory{ + { + CategoryId: 1001, + Name: "Category Name", + Type: models.CATEGORY_TYPE_EXPENSE, + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + Hidden: false, + }, + { + CategoryId: 2001, + Name: "Category Name2", + Type: models.CATEGORY_TYPE_EXPENSE, + ParentCategoryId: 1001, + Hidden: false, + }, + { + CategoryId: 1002, + Name: "Category Name3", + Type: models.CATEGORY_TYPE_INCOME, + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + Hidden: false, + }, + { + CategoryId: 2002, + Name: "Category Name4", + Type: models.CATEGORY_TYPE_INCOME, + ParentCategoryId: 1002, + Hidden: false, + }, + { + CategoryId: 1003, + Name: "Category Name5", + Type: models.CATEGORY_TYPE_TRANSFER, + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + Hidden: false, + }, + { + CategoryId: 2003, + Name: "Category Name6", + Type: models.CATEGORY_TYPE_TRANSFER, + ParentCategoryId: 1003, + Hidden: false, + }, + } + expenseCategoryMap, incomeCategoryMap, transferCategoryMap := TransactionCategories.GetVisibleSubCategoryNameMapByList(categories) + + assert.Equal(t, 1, len(expenseCategoryMap)) + assert.Contains(t, expenseCategoryMap, "Category Name2") + assert.Contains(t, expenseCategoryMap["Category Name2"], "Category Name") + + assert.Equal(t, 1, len(incomeCategoryMap)) + assert.Contains(t, incomeCategoryMap, "Category Name4") + assert.Contains(t, incomeCategoryMap["Category Name4"], "Category Name3") + + assert.Equal(t, 1, len(transferCategoryMap)) + assert.Contains(t, transferCategoryMap, "Category Name6") + assert.Contains(t, transferCategoryMap["Category Name6"], "Category Name5") +} + +func TestGetVisibleSubCategoryNameMapByList_OrphanSubCategories(t *testing.T) { + categories := []*models.TransactionCategory{ + { + CategoryId: 2001, + Name: "Category Name", + Type: models.CATEGORY_TYPE_EXPENSE, + ParentCategoryId: 9999, + Hidden: false, + }, + } + expenseCategoryMap, incomeCategoryMap, transferCategoryMap := TransactionCategories.GetVisibleSubCategoryNameMapByList(categories) + + assert.Equal(t, 0, len(expenseCategoryMap)) + assert.Equal(t, 0, len(incomeCategoryMap)) + assert.Equal(t, 0, len(transferCategoryMap)) +} + +func TestGetCategoryNames_EmptyList(t *testing.T) { + categories := make([]*models.TransactionCategory, 0) + actualNames := TransactionCategories.GetCategoryNames(categories) + + assert.NotNil(t, actualNames) + assert.Equal(t, 0, len(actualNames)) +} + +func TestGetCategoryNames_MultipleCategories(t *testing.T) { + categories := []*models.TransactionCategory{ + { + CategoryId: 1001, + Name: "Category Name", + }, + { + CategoryId: 1002, + Name: "Category Name2", + }, + { + CategoryId: 1003, + Name: "Category Name3", + }, + } + actualNames := TransactionCategories.GetCategoryNames(categories) + + assert.Equal(t, 3, len(actualNames)) + assert.Equal(t, "Category Name", actualNames[0]) + assert.Equal(t, "Category Name2", actualNames[1]) + assert.Equal(t, "Category Name3", actualNames[2]) +} + +func TestGetCategoryOrSubCategoryIdsByCategoryName_EmptyList(t *testing.T) { + categories := make([]*models.TransactionCategory, 0) + actualIds := TransactionCategories.GetCategoryOrSubCategoryIdsByCategoryName(categories, "Category Name") + + assert.NotNil(t, actualIds) + assert.Equal(t, 0, len(actualIds)) +} + +func TestGetCategoryOrSubCategoryIdsByCategoryName_NotExistName(t *testing.T) { + categories := []*models.TransactionCategory{ + { + CategoryId: 1001, + Name: "Category Name", + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + }, + } + actualIds := TransactionCategories.GetCategoryOrSubCategoryIdsByCategoryName(categories, "Non-existent Category") + + assert.NotNil(t, actualIds) + assert.Equal(t, 0, len(actualIds)) +} + +func TestGetCategoryOrSubCategoryIdsByCategoryName_ParentCategoryWithoutChildren(t *testing.T) { + categories := []*models.TransactionCategory{ + { + CategoryId: 1001, + Name: "Category Name", + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + }, + } + actualIds := TransactionCategories.GetCategoryOrSubCategoryIdsByCategoryName(categories, "Category Name") + + assert.NotNil(t, actualIds) + assert.Equal(t, 0, len(actualIds)) +} + +func TestGetCategoryOrSubCategoryIdsByCategoryName_BothParentAndSubCategory(t *testing.T) { + categories := []*models.TransactionCategory{ + { + CategoryId: 1001, + Name: "Category Name", + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + }, + { + CategoryId: 2001, + Name: "Category Name", + ParentCategoryId: 1001, + }, + { + CategoryId: 2002, + Name: "Category Name2", + ParentCategoryId: 1001, + }, + { + CategoryId: 1002, + Name: "Category Name3", + ParentCategoryId: models.LevelOneTransactionCategoryParentId, + }, + { + CategoryId: 2003, + Name: "Category Name", + ParentCategoryId: 1002, + }, + } + actualIds := TransactionCategories.GetCategoryOrSubCategoryIdsByCategoryName(categories, "Category Name") + + assert.Equal(t, 3, len(actualIds)) + assert.Contains(t, actualIds, int64(2001)) + assert.Contains(t, actualIds, int64(2002)) + assert.Contains(t, actualIds, int64(2003)) +}