Coverage for tests/conftest.py: 100%

40 statements  

« prev     ^ index     » next       coverage.py v7.15.0, created at 2026-07-05 04:36 +0000

1import pytest 

2 

3from sankey_cashflow import AppSettings, RowLabels, Transactions 

4import pandas as pd 

5 

6 

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) 

37 

38 

39@pytest.fixture 

40def make_args(): 

41 return Args 

42 

43 

44@pytest.fixture 

45def default_app_settings(make_args): 

46 return AppSettings(make_args()) 

47 

48 

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 ] 

73 

74 

75@pytest.fixture 

76def sample_row_labels(sample_labels_data): 

77 return RowLabels(sample_labels_data) 

78 

79 

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) 

97 

98 

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) 

102 

103 

104TRANSACTION_COLUMNS = [ 

105 'Date', 'Category', 'Description', 'Tags', 'Comments', 'Source', 'Target', 

106 'Type', 'Distribution', 'Amount', 'Sales Tax', 'Tips' 

107] 

108 

109 

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