Coverage for tests/conftest.py: 100%
40 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-05 04:36 +0000
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-05 04:36 +0000
1import pytest
3from sankey_cashflow import AppSettings, RowLabels, Transactions
4import pandas as pd
7class Args:
8 """
9 Stand-in for the argparse.Namespace that AppSettings expects. Every field defaults to the
10 value used by a plain `python -m sankey_cashflow ...` invocation against the sample data;
11 override individual kwargs in a test to exercise a specific branch.
12 """
13 def __init__(self, **overrides):
14 defaults = dict(
15 source='sample_data/expenses.csv',
16 audit=False,
17 sheet=None,
18 srcmap='sample_data/labels.csv',
19 range=None,
20 separate_tax=False,
21 verbose=False,
22 creds=None,
23 distributions=False,
24 all_time=False,
25 recurring=False,
26 hover=None,
27 dtype=None,
28 tags=None,
29 tag_override=False,
30 feed_in=False,
31 exclude=None,
32 stores=None,
33 )
34 defaults.update(overrides)
35 for key, value in defaults.items():
36 setattr(self, key, value)
39@pytest.fixture
40def make_args():
41 return Args
44@pytest.fixture
45def default_app_settings(make_args):
46 return AppSettings(make_args())
49@pytest.fixture
50def sample_labels_data():
51 return [
52 {
53 'Category Name': 'House',
54 'Type': 'computed',
55 'Source': 'Income',
56 'Target': 'House',
57 'Classification': 'Expense',
58 'Link color': 'rgba(153, 187, 255, 0.8)',
59 'Node color': 'rgba(102, 153, 255, 1)',
60 'Comments': ''
61 },
62 {
63 'Category Name': 'Groceries',
64 'Type': 'computed',
65 'Source': 'Income',
66 'Target': 'Groceries',
67 'Classification': 'Expense',
68 'Link color': 'rgba(153, 187, 255, 0.8)',
69 'Node color': 'rgba(102, 153, 255, 1)',
70 'Comments': ''
71 }
72 ]
75@pytest.fixture
76def sample_row_labels(sample_labels_data):
77 return RowLabels(sample_labels_data)
80@pytest.fixture
81def sample_transactions_df():
82 data = {
83 'Date': ['2023-01-01', '2023-01-02'],
84 'Category': ['Groceries', 'House'],
85 'Description': ['Grocery Store', 'Mortgage'],
86 'Tags': [None, 'Recurring'],
87 'Comments': ['', ''],
88 'Source': [None, None],
89 'Target': [None, None],
90 'Type': ['computed', 'computed'],
91 'Distribution': [None, None],
92 'Amount': [100.0, 200.0],
93 'Sales Tax': [5.0, 10.0],
94 'Tips': [2.0, 3.0],
95 }
96 return pd.DataFrame(data)
99@pytest.fixture
100def sample_transactions(sample_transactions_df, sample_row_labels, default_app_settings):
101 return Transactions(sample_transactions_df, sample_row_labels, default_app_settings)
104TRANSACTION_COLUMNS = [
105 'Date', 'Category', 'Description', 'Tags', 'Comments', 'Source', 'Target',
106 'Type', 'Distribution', 'Amount', 'Sales Tax', 'Tips'
107]
110@pytest.fixture
111def make_transactions_df():
112 """
113 Build a transactions DataFrame from partial row dicts, filling in defaults for any
114 column not specified. Column order/set must exactly match DataRow.fields for
115 Transactions._validate_df() to accept it.
116 """
117 def _make(rows):
118 defaults = {
119 'Description': '', 'Tags': None, 'Comments': '', 'Source': None, 'Target': None,
120 'Type': '', 'Distribution': None, 'Sales Tax': None, 'Tips': None,
121 }
122 full_rows = []
123 for row in rows:
124 full_row = dict(defaults)
125 full_row.update(row)
126 full_rows.append({col: full_row[col] for col in TRANSACTION_COLUMNS})
127 return pd.DataFrame(full_rows)
128 return _make